[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() 사용하기
[참고]
Updating ViewPager With New Data Dynamically
Update Fragment in ViewPager From getItemPosition