How to AsyncTask to Fragments from onPageSelected of ViewPager? - java

I'm new to Android programming.
I googled & stackoverflowed, read android docs but nothing helped me or maybe I didn't understand well.
I'm trying to AsyncTask UI to fragment via onPageSelected from ViewPager.
Like AndroMoney app ViewPager(Before onPageSelected, it shows "loading...", when onPageSelected, it AsyncTasked and loaded.):
AndroMoney ViewPager Fragment Screenshoot
but my code is: it asynctasked while swipping and sometimes it stops between two fragments like this:
my code viewpager screenshot
unlike AndroMoney app, my code doesn't asynctask onPageSelected.
here is MyFragment.java:
public class MyFragment extends Fragment {
public static final String EXTRA_MESSAGE = "EXTRA_MESSAGE";
final StringBuilder buffer=new StringBuilder();
View v;
public static final MyFragment newInstance(int message) {
MyFragment f = new MyFragment();
Bundle bdl = new Bundle(1);
bdl.putInt(EXTRA_MESSAGE, message);
f.setArguments(bdl);
return f;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
v = inflater.inflate(R.layout.myfragment_layout, container, false);
new AsyncDatabase().execute();
return v;
}
public class AsyncDatabase extends AsyncTask<Void,Void,Void>{
#Override
protected Void doInBackground(Void... params){
int message = getArguments().getInt(EXTRA_MESSAGE);
BibleService bService=new BibleServiceImpl(getActivity().getApplication());
List<Bible> bible=bService.getBibleByChapterNumber("Salm", message);
for(Bible b: bible){
for(int i=0;i<10;i++){
buffer.append(b);
}
}
return null;
}
#Override
protected void onPostExecute(Void result){
TextView txt1=(TextView)v.findViewById(R.id.textView1);
TextView txt2=(TextView)v.findViewById(R.id.textView2);
txt1.setText("Done");
txt2.setText(buffer.toString());
}
#Override
protected void onPreExecute(){
TextView txt1=(TextView)v.findViewById(R.id.textView1);
txt1.setText("Loading...");
}
#Override
protected void onProgressUpdate(Void... values){
}
}
}
here is PageViewActivity.java:
public class PageViewActivity extends FragmentActivity{
MyPageAdapter pageAdapter;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_page_view);
List<Fragment> fragments = getFragments();
pageAdapter = new MyPageAdapter(getSupportFragmentManager(), fragments);
ViewPager pager = (ViewPager) findViewById(R.id.viewpager);
pager.setOffscreenPageLimit(1);
pager.setAdapter(pageAdapter);
pager.setCurrentItem(11);
pager.setOnPageChangeListener(new OnPageChangeListener() {
public void onPageScrollStateChanged(int state) {
}
public void onPageScrolled(int position, float positionOffset,
int positionOffsetPixels) {
}
public void onPageSelected(int position) {
}
});
}
private List<Fragment> getFragments() {
List<Fragment> fList = new ArrayList<Fragment>();
for (int j = 2; j < 150; j++) {
fList.add(MyFragment.newInstance(j));
}
return fList;
}
private class MyPageAdapter extends FragmentStatePagerAdapter {
private List<Fragment> fragments;
public MyPageAdapter(FragmentManager fm, List<Fragment> fragments) {
super(fm);
this.fragments = fragments;
}
#Override
public Fragment getItem(int position) {
return this.fragments.get(position);
}
#Override
public int getCount() {
return this.fragments.size();
}
}
I tested stupidly by adding the following code:
public void onPageSelected(int position) {
new MyFragment().new AsyncDatabase().execute();
}
It didn't work.:-P
So, how to asynctask to fragment from onPageSelected of PageViewActivity like AndroMoney app.

Expose a new method in your fragment:
public void executeAsyncTask() {
new AsyncDatabase().execute();
}
In the activity, make your list of fragments final, so you can access it in the Adapter:
final List<MyFragment> fragments = getFragments();
Then change your onPageSelected() method to be:
public void onPageSelected(int position) {
fragments.get(position).executeAsyncTask();
}
You'll also need to update the MyPagerAdapter to use MyFragment instead of Fragment:
private class MyPageAdapter extends FragmentStatePagerAdapter {
private List<MyFragment> fragments;
public MyPageAdapter(FragmentManager fm, List<MyFragment> fragments) {
super(fm);
this.fragments = fragments;
}
#Override
public Fragment getItem(int position) {
return this.fragments.get(position);
}
#Override
public int getCount() {
return this.fragments.size();
}
}
private List<MyFragment> getFragments() {
List<MyFragment> fList = new ArrayList<MyFragment>();
for (int j = 2; j < 150; j++) {
fList.add(MyFragment.newInstance(j));
}
return fList;
}

Related

How to create an custom alertDialog from a tabbed fragment?

Problem:
I'm trying to open a custom dialog after pressing a button in my tabbed fragment.
It's seems like my MainActivity activity is sent to the dialog while i want my tabbed fragment(GroupFragment) to be sent so i can change the editText(for now) in this fragment.
Code:
public class GroupFragment extends Fragment implements AddGroupDialog.AddGroupDialogListener {
private Button addGroupButton;
private TextView textViewNoGroups;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_group, container, false);
addGroupButton = view.findViewById(R.id.addGroupButton);
textViewNoGroups = view.findViewById(R.id.textViewNoGroups);
addGroupButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
addNewGroupDialog();
}
});
scaleAnimation(addGroupButton);
return view;
}
private void scaleAnimation(View v){
Animator scale = ObjectAnimator.ofPropertyValuesHolder(v,
PropertyValuesHolder.ofFloat(View.SCALE_X, 0, 1.2f, 1),
PropertyValuesHolder.ofFloat(View.SCALE_Y, 0, 1.2f, 1)
);
scale.setDuration(600);
scale.start();
}
private void addNewGroupDialog(){
AddGroupDialog dialog = new AddGroupDialog();
assert getFragmentManager() != null;
dialog.show(getFragmentManager(), "add new group dialog");
}
#Override
public void applyString(String groupName) {
textViewNoGroups.setText(groupName);
}
}
public class AddGroupDialog extends AppCompatDialogFragment {
private EditText editTextGroupName;
private AddGroupDialogListener listener;
#NonNull
#Override
public Dialog onCreateDialog(#Nullable Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
LayoutInflater inflater = getActivity().getLayoutInflater();
View view = inflater.inflate(R.layout.layout_add_new_group_dialog, null);
builder.setView(view)
.setTitle("")
.setPositiveButton(R.string.confirm, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
String groupName = editTextGroupName.getText().toString();
listener.applyString(groupName);
}
});
editTextGroupName = view.findViewById(R.id.editTextGroupName);
return builder.create();
}
#Override
public void onAttach(#NonNull Context context) {
super.onAttach(context);
try {
listener = (AddGroupDialogListener) context;
} catch (ClassCastException e){
throw new ClassCastException(context.toString() +
"Must implement AddGroupDialogListener");
}
}
public interface AddGroupDialogListener{
void applyString(String groupName);
}
}
public class MainActivity extends AppCompatActivity{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
SectionsPagerAdapter sectionsPagerAdapter = new SectionsPagerAdapter(this, getSupportFragmentManager());
ViewPager viewPager = findViewById(R.id.view_pager);
viewPager.setAdapter(sectionsPagerAdapter);
TabLayout tabs = findViewById(R.id.tabs);
tabs.setupWithViewPager(viewPager);
}
}
public class SectionsPagerAdapter extends FragmentPagerAdapter {
#StringRes
private static final int[] TAB_TITLES = new int[]{R.string.tab_text_1, R.string.tab_text_2, R.string.tab_text_3};
private final Context mContext;
public SectionsPagerAdapter(Context context, FragmentManager fm) {
super(fm);
mContext = context;
}
#Override
public Fragment getItem(int position) {
Fragment fragment = null;
switch (position){
case 0:
fragment = new GroupFragment();
break;
case 1:
fragment = new AttendanceFragment();
break;
case 2:
fragment = new StatisticsFragment();
break;
}
return fragment;
}
#Nullable
#Override
public CharSequence getPageTitle(int position) {
return mContext.getResources().getString(TAB_TITLES[position]);
}
#Override
public int getCount() {
return TAB_TITLES.length;
}
}
Error:
java.lang.ClassCastException: com.example.attendencetaker.MainActivity#26602bcMust implement AddGroupDialogListener
I hope my explanation of the problem is clear. Thank you!
Make the activity implement your interfaces and so on and then pass all data to the fragment with an method on the fragment. You will need an reference to actual Fragment that is displayed.
In your fragment add a method similar to this:
public void updateData(String data) {
editText.setText(data);
}
And in the override method of the interface in your activity to this:
#Override
public void update(String data) {
fragment.updateData(data);
}
Update
Use this Adapter instead:
public class SectionTabAdapter extends FragmentPagerAdapter {
private ArrayList<Fragment> fragments = new ArrayList<>();
private ArrayList<String> titles = new ArrayList<>();
public SectionTabAdapter(#NonNull FragmentManager fm, int behavior) {
super(fm, behavior);
}
public void addFragment(Fragment fragment, String title) {
fragments.add(fragment);
titles.add(title);
}
#NonNull
#Override
public Fragment getItem(int position) {
return fragments.get(position);
}
#Override
public int getCount() {
return fragments.size();
}
#Nullable
#Override
public CharSequence getPageTitle(int position) {
return titles.get(position);
}
}
In your activity then do this:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
SectionsPagerAdapter sectionTabAdapter = new SectionTabAdapter(this, getSupportFragmentManager());
Fragment groupFragment = new GroupFragment();
Fragment attendanceFragment = new AttendanceFragment();
Fragment statisticsFragment = new StatisticsFragment();
sectionTabAdapter.addFragment(groupFragment, context.getString(R.string.title_1);
sectionTabAdapter.addFragment(attendanceFragment, context.getString(R.string.title_2);
sectionTabAdapter.addFragment(statisticsFragment, context.getString(R.string.title_3);
ViewPager viewPager = findViewById(R.id.view_pager);
viewPager.setAdapter(sectionTabAdapter);
TabLayout tabs = findViewById(R.id.tabs);
tabs.setupWithViewPager(viewPager);
}

Dynamically create tabs in Tablayout from a list?

My app creates drawer submenus from sharedpreference values. These submenus are basically called "interests" or categories. I'm trying to move this same functionality to tablayout since that is much more convenient but can't seem to get it to work!
Edit: New code based on suggestions.
TabsFragment:
public class HomeTabsFragment extends Fragment implements ViewPager.OnPageChangeListener {
private View view;
private SectionsPagerAdapterHome homePageAdapter;
public ViewPager viewPager;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
this.view = inflater.inflate(R.layout.fragment_articles_tabs, container, false);
TabLayout tabLayout = view.findViewById(R.id.home_list_tabs);
viewPager = view.findViewById(R.id.home_list_tabs_container);
homePageAdapter = new SectionsPagerAdapterHome(getFragmentManager());
viewPager.setAdapter(homePageAdapter);
viewPager.setOffscreenPageLimit(tabLayout.getTabCount());
viewPager.addOnPageChangeListener(this);
tabLayout.setupWithViewPager(viewPager);
if(SharedPrefernces.getUserInterests()!=null) {
List<String> my_interests = SharedPrefernces.getUserInterests();
Collections.sort(my_interests, String::compareToIgnoreCase);
my_interests.add(0, getString(R.string.all_stories));
for (String interest : my_interests) {
homePageAdapter.addTabPage(new FeedsFragment(), interest);
}
}
return view;
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
// Do something that differs the Activity's menu here
super.onCreateOptionsMenu(menu, inflater);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
return false;
}
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
Fragment fragment = homePageAdapter.getFragment(position);
if (fragment != null) {
fragment.onResume();
}
}
#Override
public void onPageScrollStateChanged(int state) {
}
}
Adapter:
public class SectionsPagerAdapterHome extends FragmentPagerAdapter {
private FragmentManager fragmentManager;
private ArrayList fragmentTags = new ArrayList();
private ArrayList<String> titles = new ArrayList();
protected SectionsPagerAdapterHome(FragmentManager fm) {
super(fm, FragmentPagerAdapter.BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
fragmentManager = fm;
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
Object object = super.instantiateItem(container, position);
if (object instanceof Fragment) {
Fragment fragment = (Fragment) object;
String tag = fragment.getTag();
fragmentTags.add(position, tag);
}
return object;
}
public Fragment getFragment(int position) {
Fragment fragment = null;
Object tag = fragmentTags.get(position);
if (tag != null) {
fragment = fragmentManager.findFragmentByTag(String.valueOf(tag));
}
return fragment;
}
#Override
public Fragment getItem(int position) {
return FeedsFragment.newInstance();
}
public void addTabPage(Fragment fragment,String title) {
titles.add(title);
fragmentTags.add(fragment);
notifyDataSetChanged();
}
#Override
public int getCount() {
return fragmentTags.size();
}
#Override
public CharSequence getPageTitle(int position) {
return titles.get(position);
}
}
I'm not sure how I can achieve this so need help.
Since you are using a ViewPager with an Adapter instead of using tabLayout.addTab(...) you have to add the item in the adapter.
Something like:
public class SectionsPagerAdapterHome extends FragmentPagerAdapter {
private ArrayList fragmentTags = new ArrayList();
private ArrayList<String> titles = new ArrayList();
//.....
public void addTabPage(Fragment fragment,String title) {
titles.add(title);
fragmentTags.add(fragment);
notifyDataSetChanged();
}
#Override
public int getCount() {
return fragmentTags.size();
}
#Override
public CharSequence getPageTitle(int position) {
return tables.get(position);
}
}

How to use getChildFragmentManager with a class that extends Dialog fragment

I am a having a fragment with TabLayout. As soon as I move from TabLayout Fragment to the next Fragment and press the back key. The content on the default TabLayout fragment disappears. I found a possible solution to this in the post. Following is the code for the TabLayout.
public class IndividualCollectionSheetFragment extends MifosBaseFragment {
private TabLayout tabLayout;
private ViewPager viewPager;
private View rootView;
public IndividualCollectionSheetFragment() {
}
public static IndividualCollectionSheetFragment newInstance() {
Bundle args = new Bundle();
IndividualCollectionSheetFragment fragment = new IndividualCollectionSheetFragment();
fragment.setArguments(args);
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater,
#Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.fragment_individual_recycler, container, false);
ButterKnife.bind(this, rootView);
setToolbarTitle(getStringMessage(R.string.individual_collection_sheet));
viewPager = rootView.findViewById(R.id.viewpager);
setupViewPager(viewPager);
tabLayout = rootView.findViewById(R.id.tabs);
tabLayout.setupWithViewPager(viewPager);
return rootView;
}
private void setupViewPager(ViewPager viewPager) {
ViewPagerAdapter adapter = new ViewPagerAdapter(getActivity().getSupportFragmentManager());
adapter.addFragment(new NewIndividualCollectionSheetFragment(), Constants.NEW);
adapter.addFragment(new SavedIndividualCollectionSheetFragment(), Constants.SAVED);
viewPager.setAdapter(adapter);
}
class ViewPagerAdapter extends FragmentPagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
public ViewPagerAdapter(FragmentManager manager) {
super(manager);
}
#Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
#Override
public int getCount() {
return mFragmentList.size();
}
public void addFragment(Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
#Override
public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position);
}
}
}
The solution in the post suggested using getChildFramentManager instead of getSupportFragmentManager. As soon as I changed to getChildFragmentManager. I got the error.
java.lang.IllegalStateException: Fragment CollectionSheetDialogFragment{572dd42 #0 Identifier Dialog Fragment} declared target fragment NewIndividualCollectionSheetFragment{45e8153 #0 id=0x7f090361 android:switcher:2131297121:0} that does not belong to this FragmentManager!
which might be because of the class CollectionSheetDialogFragment which extends DialogFragment and there must be inconsistencies with the different Fragment Managers being used.
NewIndividualCollectionSheet.java(first fragment in tablayout)
public class NewIndividualCollectionSheetFragment extends MifosBaseFragment implements
IndividualCollectionSheetMvpView, MFDatePicker.OnDatePickListener,
Spinner.OnItemSelectedListener, View.OnClickListener {
#BindView(R.id.btn_fetch_collection_sheet)
Button btnFetchSheet;
#BindView(R.id.sp_office_list)
Spinner spOffices;
#BindView(R.id.sp_staff_list)
Spinner spStaff;
#BindView(R.id.tv_repayment_date)
TextView tvRepaymentDate;
#Inject
NewIndividualCollectionSheetPresenter presenter;
private IndividualCollectionSheet sheet;
private DialogFragment datePicker;
private RequestCollectionSheetPayload requestPayload;
private View rootView;
private ArrayAdapter<String> officeAdapter;
private ArrayList<String> officeNameList;
private List<Office> officeList;
private ArrayAdapter<String> staffAdapter;
private ArrayList<String> staffNameList;
private List<Staff> staffList;
private int officeId;
private int staffId;
private int requestCode = 1;
private boolean success = true;
private String actualDisbursementDate;
private String transactionDate;
public NewIndividualCollectionSheetFragment() {
}
public static NewIndividualCollectionSheetFragment newInstance() {
Bundle args = new Bundle();
NewIndividualCollectionSheetFragment fragment = new NewIndividualCollectionSheetFragment();
fragment.setArguments(args);
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
((MifosBaseActivity) getActivity()).getActivityComponent().inject(this);
if (savedInstanceState != null) {
sheet = (IndividualCollectionSheet) savedInstanceState.get(
Constants.EXTRA_COLLECTION_INDIVIDUAL);
}
setHasOptionsMenu(true);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.fragment_new_collection_sheet, container, false);
ButterKnife.bind(this, rootView);
setToolbarTitle(getStringMessage(R.string.individual_collection_sheet));
presenter.attachView(this);
setUpUi();
return rootView;
}
private void setUpUi() {
setRepaymentDate();
officeNameList = new ArrayList<>();
officeAdapter = new ArrayAdapter<>(getActivity(),
android.R.layout.simple_spinner_item, officeNameList);
officeAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spOffices.setAdapter(officeAdapter);
spOffices.setOnItemSelectedListener(this);
staffNameList = new ArrayList<>();
staffAdapter = new ArrayAdapter<>(getActivity(),
android.R.layout.simple_spinner_item, staffNameList);
staffAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spStaff.setAdapter(staffAdapter);
tvRepaymentDate.setOnClickListener(this);
btnFetchSheet.setOnClickListener(this);
presenter.fetchOffices();
}
void setRepaymentDate() {
datePicker = MFDatePicker.newInsance(this);
String date = DateHelper.
getDateAsStringUsedForCollectionSheetPayload(MFDatePicker.getDatePickedAsString());
tvRepaymentDate.setText(date.replace('-', ' '));
transactionDate = date.replace('-', ' ');
actualDisbursementDate = transactionDate;
}
private void prepareRequestPayload() {
requestPayload = new RequestCollectionSheetPayload();
requestPayload.setOfficeId(officeId);
requestPayload.setStaffId(staffId);
requestPayload.setTransactionDate(tvRepaymentDate.getText().toString());
}
#Override
public void setOfficeSpinner(List<Office> offices) {
officeList = offices;
officeNameList.clear();
officeNameList.add(getString(R.string.spinner_office));
officeNameList.addAll(presenter.filterOffices(officeList));
officeAdapter.notifyDataSetChanged();
}
#Override
public void onDatePicked(String date) {
String d = DateHelper.getDateAsStringUsedForCollectionSheetPayload(date);
tvRepaymentDate.setText(d.replace('-', ' '));
}
public void retrieveCollectionSheet() {
prepareRequestPayload();
presenter.fetchIndividualCollectionSheet(requestPayload);
}
public void setTvRepaymentDate() {
datePicker.show(getActivity().getSupportFragmentManager(),
FragmentConstants.DFRAG_DATE_PICKER);
}
#Override
public void setStaffSpinner(List<Staff> staffs) {
spStaff.setOnItemSelectedListener(this);
staffList = staffs;
staffNameList.clear();
staffNameList.add(getString(R.string.spinner_staff));
staffNameList.addAll(presenter.filterStaff(staffList));
staffAdapter.notifyDataSetChanged();
}
#Override
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
switch (adapterView.getId()) {
case R.id.sp_office_list:
if (i == officeList.size() || i == 0) {
Toaster.show(rootView, getStringMessage(R.string.error_select_office));
} else {
Toaster.show(rootView, officeNameList.get(i));
officeId = officeList.get(i - 1).getId();
presenter.fetchStaff(officeId);
}
break;
case R.id.sp_staff_list:
if (i == staffList.size() || i == 0) {
Toaster.show(rootView, getStringMessage(R.string.error_select_staff));
} else {
staffId = staffList.get(i - 1).getId();
}
break;
}
}
public void popupDialog() {
CollectionSheetDialogFragment collectionSheetDialogFragment =
CollectionSheetDialogFragment.newInstance(tvRepaymentDate.getText().toString(),
sheet.getClients().size());
collectionSheetDialogFragment.setTargetFragment(this, requestCode);
FragmentTransaction fragmentTransaction = getActivity().getSupportFragmentManager()
.beginTransaction();
fragmentTransaction.addToBackStack(FragmentConstants.FRAG_DOCUMENT_LIST);
collectionSheetDialogFragment.show(fragmentTransaction, "Identifier Dialog Fragment");
}
public void getResponse(String response) {
switch (response) {
case "FillNow":
FragmentManager fm = getActivity()
.getSupportFragmentManager();
fm.popBackStack();
IndividualCollectionSheetDetailsFragment frag = new
IndividualCollectionSheetDetailsFragment().newInstance(sheet,
actualDisbursementDate, transactionDate);
((MifosBaseActivity) getActivity()).replaceFragment(frag,
true, R.id.container);
break;
}
}
#Override
public void onNothingSelected(AdapterView<?> adapterView) {
}
#Override
public void showSheet(IndividualCollectionSheet individualCollectionSheet) {
sheet = individualCollectionSheet;
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putParcelable(Constants.EXTRA_COLLECTION_INDIVIDUAL, sheet);
}
#Override
public void showSuccess() {
if (success) {
popupDialog();
}
}
#Override
public void showError(String message) {
Toaster.show(rootView, message);
}
#Override
public void showNoSheetFound() {
success = false;
Toaster.show(rootView, getStringMessage(R.string.no_collectionsheet_found));
}
#Override
public void showProgressbar(boolean b) {
if (b) {
showMifosProgressDialog();
} else {
hideMifosProgressDialog();
}
}
#Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.tv_repayment_date:
setTvRepaymentDate();
break;
case R.id.btn_fetch_collection_sheet:
retrieveCollectionSheet();
break;
}
}
}
CollectionSheetDialogFragment.java
public class CollectionSheetDialogFragment extends DialogFragment {
#BindView(R.id.tv_due_date)
TextView tvDueDate;
#BindView(R.id.tv_members)
TextView tvMembers;
#BindView(R.id.btn_fillnow)
Button btnFillnow;
#BindView(R.id.btn_cancel)
Button btnCancel;
private View rootView;
private String date;
private int members;
public CollectionSheetDialogFragment() {
}
public static CollectionSheetDialogFragment newInstance(String date, int members) {
CollectionSheetDialogFragment collectionSheetDialogFragment =
new CollectionSheetDialogFragment();
Bundle args = new Bundle();
args.putString(Constants.REPAYMENT_DATE, date);
args.putInt(Constants.MEMBERS, members);
collectionSheetDialogFragment.setArguments(args);
return collectionSheetDialogFragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
((MifosBaseActivity) getActivity()).getActivityComponent().inject(this);
date = getArguments().getString(Constants.REPAYMENT_DATE);
members = getArguments().getInt(Constants.MEMBERS);
super.onCreate(savedInstanceState);
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable
ViewGroup container, Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.fragment_collection_sheet_dialog, container, false);
ButterKnife.bind(this, rootView);
return rootView;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
tvDueDate.setText(date);
tvMembers.setText(Integer.toString(members));
}
#OnClick(R.id.btn_fillnow)
public void setBtnFillnow() {
((NewIndividualCollectionSheetFragment) getTargetFragment()).getResponse("FillNow");
}
#OnClick(R.id.btn_cancel)
public void setBtnCancel() {
getDialog().dismiss();
}
}
Can someone help me get around this error so I can persist the TabLayout On back press?
Maybe This Work :
Replace getFragmentManager() instead of getChildFragmentManager()
Try this changing seupViewPager() in IndividualCollectionSheetFragment.java like this
private void setupViewPager(ViewPager viewPager) {
ViewPagerAdapter adapter = new ViewPagerAdapter(getActivity().getChildFragmentManager());
adapter.addFragment(new NewIndividualCollectionSheetFragment(), Constants.NEW);
adapter.addFragment(new SavedIndividualCollectionSheetFragment(), Constants.SAVED);
viewPager.setAdapter(adapter);
}

Change displayed fragment inside ViewPager

I have ViewPager that is showing fragments : SearchFragment,FriendFragment. What I am struggling to do is to change SearchFragment to ChatFragment
There is a lot of feedback in replace-fragment-inside-a-viewpager/ yet I have some trouble with making any of these solutions work.
I think there might be something wrong with my way of creating interface, I had some trouble to make it callable from ViewPager as SearchActivity.newInstance(new MyListener {...} )
I reached the point now where I get
java.lang.NullPointerException: Attempt to invoke virtual method
'android.support.v4.app.FragmentTransaction
android.support.v4.app.FragmentManager.beginTransaction()' on a null
object reference
at
com.example.ashaneen.firebaseapp.adapters.MainScreenAdapter$1.onFragmentChange(MainScreenAdapter.java:44)
at
com.example.ashaneen.firebaseapp.fragments.SearchFragment$4.onComplete(SearchFragment.java:132)
MainScreenAdapter.class
public class MainScreenAdapter extends FragmentPagerAdapter implements SearchFragment.MyListener {
private static final String TAG = "MainScreenAdapter";
private FragmentManager fragmentManager;
private Fragment fragment1;
public MainScreenAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position)
{
switch (position)
{
case 0:
if (fragment1 == null)
{
fragment1 = SearchFragment.newInstance(new SearchFragment.MyListener() {
#Override
public void onFragmentChange() {
fragmentManager.beginTransaction().remove(fragment1).commit();
fragment1 = ChatFragment.newInstance();
notifyDataSetChanged();
}
});
}
return fragment1;
case 1:
return new FriendsFragment();
default:
return new ChatFragment();
}
}
#Override
public int getItemPosition(#NonNull Object object) {
return POSITION_NONE;
}
#Override
public void onFragmentChange() {
}
SearchFragment.class
public class SearchFragment extends android.support.v4.app.Fragment {
public SearchFragment() {
}
private String TAG = "Profile2Fragment";
public interface MyListener
{
void onFragmentChange();
}
static MyListener myListener = new MyListener() {
public void onFragmentChange() {
}
};
public static SearchFragment newInstance(MyListener myListener) {
SearchFragment.myListener = myListener;
return new SearchFragment();
}
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_search, container, false);
button = view.findViewById(R.id.btn_search);
waitingRoomReference = db.collection("awaiting_room");
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view)
{
myListener.onFragmentChange();
}
}
});
return view;
}
Try changing this
public MainScreenAdapter(FragmentManager fm) {
super(fm);
}
to
public MainScreenAdapter(FragmentManager fm) {
super(fm);
fragmentManager = fm;
}

ChildFragmentManager java.lang.IllegalStateException: Activity has been destroyed

I have tried to add a fragment inside another fragment inside viewpager using getChildFragmentManager(). I got following error,
java.lang.IllegalStateException: Activity has been destroyed
at android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1549)
at android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:654)
at android.support.v4.app.BackStackRecord.commitAllowingStateLoss(BackStackRecord.java:625)
at com.lakeba.gameon.userprofile.UserProfileContainerFragment.replaceFragment(UserProfileContainerFragment.java:72)
And I tried this workaround but still getting same error.
UserProfileContainerFragment.java
public class UserProfileContainerFragment extends CustomFragment {
private View rootView;
private Fragment fragment1;
public UserProfileContainerFragment() {
// Required empty public constructor
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
}
public static UserProfileContainerFragment newInstance() {
UserProfileContainerFragment fragment = new UserProfileContainerFragment();
return fragment;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
rootView = inflater.inflate(R.layout.fragment_user_profile_container, container, false);
if(savedInstanceState == null) {
UserProfileFragment userProfileFragment = UserProfileFragment.newInstance();
getChildFragmentManager().beginTransaction()
.replace(R.id.user_profile_container, userProfileFragment)
.commitAllowingStateLoss();
}
return rootView;
}
/*#Override
public void onSaveInstanceState(Bundle outState) {
//super.onSaveInstanceState(outState);
}*/
public void replaceFragment(Fragment fragment, boolean addToBackStack){
fragment1 = fragment;
if(addToBackStack){
/*getChildFragmentManager().beginTransaction()
.replace(R.id.user_profile_container, fragment)
.addToBackStack(null)
.commit();*/
getChildFragmentManager().beginTransaction()
.replace(R.id.user_profile_container, fragment)
.addToBackStack(null)
.commit();
//.commitAllowingStateLoss();
}
else{
getChildFragmentManager().beginTransaction()
.replace(R.id.user_profile_container, fragment)
.commit();
//.commitAllowingStateLoss();
}
}
#Override
public void onDetach() {
super.onDetach();
try {
Field childFragmentManager = Fragment.class.getDeclaredField("mChildFragmentManager");
childFragmentManager.setAccessible(true);
childFragmentManager.set(this, null);
} catch (NoSuchFieldException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
}
HomeMapActivity.java
public class HomeMapActivity extends AppCompatActivity implements UserProfileFragment.OnUserProfileFragmentListener{
private Toolbar homeToolbar;
private ViewPager homeViewPager;
private TabLayout homeTabLayout;
private UserProfileContainerFragment userProfileContainerFragment;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home_map);
/*homeToolbar = (Toolbar) findViewById(R.id.home_toolbar);
setSupportActionBar(homeToolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);*/
homeViewPager = (ViewPager) findViewById(R.id.home_view_pager);
HomeViewPagerAdapter homeViewPagerAdapter = new HomeViewPagerAdapter(getSupportFragmentManager());
userProfileContainerFragment = new UserProfileContainerFragment();
homeViewPagerAdapter.addFragment(new UserProfileContainerFragment(),"Profile");
homeViewPager.setAdapter(homeViewPagerAdapter);
homeTabLayout = (TabLayout) findViewById(R.id.home_tabs);
homeTabLayout.setupWithViewPager(homeViewPager);
setTabIcons(homeTabLayout);
homeTabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
#Override
public void onTabSelected(TabLayout.Tab tab) {
int tabPosition = tab.getPosition();
tab.setIcon(tabIconsArrayActivated[tabPosition]);
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
int tabPosition = tab.getPosition();
tab.setIcon(tabIconsArray[tabPosition]);
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
int tabPosition = tab.getPosition();
tab.setIcon(tabIconsArrayActivated[tabPosition]);
}
});
homeTabLayout.getTabAt(1).select();
}
private void setTabIcons(TabLayout homeTabLayout) {
homeTabLayout.getTabAt(0).setIcon(tabIconsArray[0]);
homeTabLayout.getTabAt(1).setIcon(tabIconsArray[1]);
homeTabLayout.getTabAt(2).setIcon(tabIconsArray[2]);
homeTabLayout.getTabAt(3).setIcon(tabIconsArray[3]);
}
#Override
public void onUserProfileEditButtonClicked() {
userProfileContainerFragment.replaceFragment(EditUserProfileFragment.newInstance(),true);
}
private class HomeViewPagerAdapter extends FragmentStatePagerAdapter{
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
public HomeViewPagerAdapter(FragmentManager fm) {
super(fm);
}
#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);
return null;
}
public void addFragment(Fragment fragment,String title){
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
}
}
If you look at the code in your onCreate() method you'll see the lines:
userProfileContainerFragment = new UserProfileContainerFragment();
homeViewPagerAdapter.addFragment(new UserProfileContainerFragment(),"Profile");
You first initialize the userprofileContainerFragment field with a new instance of UserProfileContainerFragment and then right below you create a new instance of UserProfileContainerFragment to be used in the ViewPager(you can easily observe this by placing a log statement in the constructor of UserProfileContainerFragment...you'll see two instances being created). Later in your code you try to use the field userProfileContainerFragment which will lead to a failure as that instance of UserProfileContainerFragment is not attached to the activity at all(this isn't the fragment used by the ViewPager).
Your code should look like below, to maintain the proper reference and not create detached fragments:
userProfileContainerFragment = new UserProfileContainerFragment();
homeViewPagerAdapter.addFragment(userProfileContainerFragment,"Profile");

Categories