Android

[Android, 안드로이드] ViewPager 사용시 Fragment 동적 처리방법

ViewPager 사용시 Fragment 동적 처리

ViewPager와 Fragment를 사용하여 앱 개발시 리시버로 부터 전달받은 데이터를 토대로 Fragment에 데이터를 전달하여 UI를 변경해야할 경우 참고하세요. 

첫번째로 어댑터 클래스를 생성 후 리시버로 부터 리턴받을 메소드를 하나 구현합니다. 아래 코드에서 update() 메소드가 호출 되면 어댑터에게 데이터가 변경되었음을 알리는 notifyDataSetChanged()메소드를 호출하고 있습니다.  호출이 완료되면 getItemPosition()메소드가 자동으로 호출됩니다. 이 메소드 안에서 해당 Fragment인지 체크 후 updateUI()메소드를 호출합니다.  updateUI()는 UpdateableFragment인터페이스 클래스를 하나 생성 후 빈 메소드를 선언합니다. 

import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentPagerAdapter;
import androidx.fragment.app.FragmentStatePagerAdapter;

import java.util.ArrayList;
import java.util.List;
 

public class ViewPagerAdapter extends FragmentStatePagerAdapter {
    private final List<Fragment> mFragmentList = new ArrayList<>();
    private final List<String> mFragmentTitleList = new ArrayList<>();
  
    String technology;
    int status; 

    public ViewPagerAdapter(FragmentManager manager) {
        super(manager);
    }

    @Override
    public Fragment getItem(int position) {
        return mFragmentList.get(position);
    }

    @Override
    public int getCount() {
        return mFragmentList.size();
    }

    @Override
    public CharSequence getPageTitle(int position) {
        return mFragmentTitleList.get(position);
    }

    @Override
    public int getItemPosition(@NonNull Object object) { 
        if (object instanceof HomeFragment) {
            ((UpdateableFragment) object).updateUI(status, technology);
        }

        //don't return POSITION_NONE, avoid fragment recreation.
        return super.getItemPosition(object);
    }

    //call this method to update fragments in ViewPager dynamically
    public void update(int _status, String _technology) {
        status =_status; 
        technology = _technology;
        notifyDataSetChanged();
    } 

    public void addFrag(Fragment fragment, String title) {
        mFragmentList.add(fragment);
        mFragmentTitleList.add(title);
    }
}

update()메소드에서 notifyDataSetChanged()를 호출해야 getItemPositon()메소드가 자동 호출 됩니다. 하지만 딜레이가 있기 때문에 바로 UI에 적용되지않는다. 바로 적용하려면 getItem()메소드를 오버라이드처리하여 Fragment에 데이터를 전달하여 처리해야한다.

@Override
public Fragment getItem(int position) {
	switch (position) {
		case 0:
			return HomeFragment.newInstance(status ,technology);
	}

	return mFragmentList.get(position);
}

[UpdateableFragment] 인터페이스

public interface UpdateableFragment {
    public void updateUI(int status, String technology);
}

생성한 인터페이스를 데이터 전달이 필요한 프레그먼트에서 implements 처리 후 updateUI메소드를 오버라이드 처리합니다.

[HomeFragment] 클래스

import android.os.Bundle;
import androidx.fragment.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class HomeFragment extends Fragment implements UpdateableFragment { 

	private static final String ARG_PARAM1 = "status";
	private static final String ARG_PARAM2 = "technology";    
	TextView status_text;
    String technology;
    int status;
    
    public static HomeFragment newInstance(int status, String technology) {
        HomeFragment fragment = new HomeFragment();
        Bundle args = new Bundle();
        args.putInt(ARG_PARAM1, status);       
        args.putString(ARG_PARAM7, technology); 
        fragment.setArguments(args);
        return fragment;
    }    
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getArguments() != null) {
            status = getArguments().getInt(ARG_PARAM1);        
            technology = getArguments().getString(ARG_PARAM2);          
        }
    }    
 
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {

		View view = inflater.inflate(R.layout.fragment_home, container, false);
        status_text = view.findViewById(R.id.ratio_text);
        
        // Inflate the layout for this fragment
        status_text.setText(technology);
        return view;
    }
    
    @Override
    public void updateUI(int _status, String _technology) {
        status =_status;       
        technology = _technology;

        //UI 처리
        status_text.setText(technology);
    }    
}

[fragment_home.xml]

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".HomeFragment">
 
    <TextView
        android:id="@+id/status_text"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="홈" />

</FrameLayout>

[브로드케스터 리시버에서 처리]

private BroadcastReceiver mainViewReceiver = new BroadcastReceiver() {
	Intent bIntent;

	@Override
	public void onReceive(Context context, Intent receiveIntent) {
		this.bIntent = receiveIntent;
		String action = bIntent.getAction();
		if (bIntent != null && action != null) {  

          fragmentViewPagerAdapter.update(           
          	,bIntent.getIntExtra("PARAM1")
          	,bIntent.getStringExtra("PARAM2"));
 
		}
	}
};

[MainActivity] 클래스

ViewPagerAdapter fragmentViewPagerAdapter;

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
	super.onCreate(savedInstanceState);
	setContentView(R.layout.activity_main);
	ViewPager viewPager = findViewById(R.id.viewpager);
 	TabLayout tabLayout = findViewById(R.id.tablayout);
    
    //어댑터 할당
	FragmentManager fragmentManager = getSupportFragmentManager();
	fragmentViewPagerAdapter = new MyViewPagerAdapter(fragmentManager);

	//프레그먼트 추가
	fragmentViewPagerAdapter.addFrag(new HomeFragment(), "홈");
	fragmentViewPagerAdapter.addFrag(new SettingsFragment(), "설정");
	fragmentViewPagerAdapter.addFrag(new NotiFragment(), "알림");

	// 뷰페이저에 어댑터 설정
	viewPager.setAdapter(fragmentViewPagerAdapter);    
    
    //탭레이아웃에 뷰페이저 설정
	tabLayout.setupWithViewPager(viewPager);
}

[연관]

[Android] TabLayout과  ViewPager 함께 사용하는 방법 (Fragment)

[Android] ViewPager.OnPageChangeListener() deprecated 에 따른 대체 메소드 addOnPageChangeListener() 사용하기

[참고]

Update ViewPager dynamically?

Updating ViewPager With New Data Dynamically

Update Fragment in ViewPager From getItemPosition

Leave a Reply

error: Content is protected !!