I've looked in other threads, and they all show how to do this on creation of the fragment, not asynchronously.
I had 3 activities, each of these activities did an asynchronous okhttp3.HttpUrl get in order to receive data from a third party JSON API. Then when complete, it would populate the activity with data.
I have since converted these 3 activities to fragments and put them in a parent activity. However, this means every time I load the new parent activity, it does THREE okhttp3.HttpUrl fetches to populate the 3 fragments.
All three fetches go to the same URL, so I was thinking to instead put the okhttp3.HttpUrl request in the parent activity and once its done, send the entire JSON package down to the fragments. This is after creation of the fragments... so I have no idea how to do this...
Any ideas?
My Parent Activity:
public class ChallongeEvent extends AppCompatActivity {
private TextView tab_text;
private String EVENT_ID, URL;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_challonge_event);
init();
}
private void init() {
tab_text = (TextView) findViewById(R.id.tab_text);
Intent intent = getIntent();
EVENT_ID = intent.getStringExtra("event_id");
if (Challonge.SUBDOMAIN.isEmpty()) {
URL = "https://api.challonge.com/v1/tournaments/" + EVENT_ID + ".json";
} else {
URL = "https://api.challonge.com/v1/tournaments/" + Challonge.SUBDOMAIN + "-" + EVENT_ID + ".json";
}
String titles[] = new String[] { getString(R.string.players), getString(R.string.matches) };
int numTabs = intent.getIntExtra("num_tabs", 1);
EventAdapter adapter = new EventAdapter(getSupportFragmentManager(), titles, numTabs);
ViewPager pager = (ViewPager) findViewById(R.id.pager);
pager.setAdapter(adapter);
pager.setCurrentItem(intent.getIntExtra("num_tabs", 1) - 1);
SlidingTabLayout sliding_tabs = (SlidingTabLayout) findViewById(R.id.sliding_tabs);
sliding_tabs.setDistributeEvenly(true);
sliding_tabs.setViewPager(pager);
}
private void populate() {
AsyncGet fetch = new AsyncGet(new AsyncResponse() {
#Override
public void processFinish(String output) {
}
});
HttpUrl.Builder urlBuilder = HttpUrl.parse(URL).newBuilder();
urlBuilder.addQueryParameter("api_key", Challonge.API_KEY);
urlBuilder.addQueryParameter("include_participants", "1");
urlBuilder.addQueryParameter("include_matches", "1");
fetch.execute(urlBuilder.build().toString());
}
public void setTabText(String text) {
tab_text.setText(text);
}
}
class EventAdapter extends FragmentPagerAdapter {
private final String[] titles;
private final int numTabs;
public EventAdapter(FragmentManager fm, String mTitles[], int mNumTabs) {
super(fm);
this.titles = mTitles;
this.numTabs = mNumTabs;
}
#Override
public Fragment getItem(int position) {
switch (position)
{
case 1:
return new ChallongeMatches();
default:
return new ChallongePlayers();
}
}
#Override
public String getPageTitle(int position) {
return titles[position];
}
#Override
public int getCount() {
return numTabs;
}
}
Please try this code
Bundle bundle = new Bundle();
bundle.putString("key", "value");
// to send object use below code
// bundle.putSerializable("key", object);
Fragment fragment = new Fragment();
fragment.setArguments(bundle);
getSupportFragmentManager().beginTransaction().replace(R.id.container, fragment).commit();
to get value use below code
String value= getIntent().getExtras().getString("value");
or
Object object = getIntent().getExtras().getSerializable("value");
You can also use a LocalBroadcastManager to send the data to all three fragments. Here's a tutorial on how to use this as well. The nice thing about this is that you can send the data, even if no one is listening, and easily add another receiver without having to change anything from the sender.
Solved it myself... in my AsyncFetch call I put:
AsyncGet fetch = new AsyncGet(new AsyncResponse() {
#Override
public void processFinish(String output) {
for (Fragment fragment : getSupportFragmentManager().getFragments())
{
if (fragment instanceof ChallongePlayers) {
((ChallongePlayers) fragment).parsePlayers(output);
} else if (fragment instanceof ChallongeMatches) {
((ChallongeMatches) fragment).parseMatches(output);
}
}
}
});
This parses through all the possible fragments in the activity and sends the data to specific actions.
make a method in each fragments :
public void setData(Bundle bundle){
//set you data to a local variable,
//and set it to the views on creation,
//OR
//call this method on Post execute of your async task
}
then in the main activity:
YourFragment fragment = new YourFragment;
fragment.setData(bundle);
getSupportFragmentManager().replace(R.id.frame, fragment).commit;
OR
call the fragment.setData(bundle) on the onPostExecute() of your async task
Related
This question already has answers here:
Passing ArrayList from Fragment class to Activity
(2 answers)
Closed 5 years ago.
please give me good solution I need your help!.
I want to pass parameter using Interface class
from B Fragment to Activity and from Activity to C Fragment.
But Service asynctask I don't know C waiting for B ?
Please explain me this Fragments do what ?
EDIT:
public class FeedDetailActivity extends AppCompatActivity implements TabFragment_DetailFeed.ArrayPasser {
private Toolbar toolbar;
private TabLayout tabLayout;
private ViewPager viewPager;
String nameSurname;
int feedId;
public ArrayList<String> pathimg;
Bundle bundle;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_feeddetail);
// toolbar = (Toolbar) findViewById(R.id.toolbar);
// setSupportActionBar(toolbar);
// getSupportActionBar().setDisplayHomeAsUpEnabled(true);
nameSurname = getIntent().getStringExtra("nameSurname");
Intent i = getIntent();
feedId = i.getIntExtra("feedId",0); // 20 for default value
// feedId = getIntent().getStringExtra("feedId"); // Hata burda
viewPager = (ViewPager) findViewById(R.id.pager);
setupViewPager(viewPager);
tabLayout = (TabLayout) findViewById(R.id.tab_layout);
tabLayout.setupWithViewPager(viewPager);
/* TabFragment_DetailComment EditTextinden otomatik klavye açtırmasını kapatmasını sağlıyor. */
getWindow().setSoftInputMode(
WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN
);
}
public String getNameSurname() {
return nameSurname;
}
public int getFeedId() {
return feedId;
}
private void setupViewPager(ViewPager viewPager) {
FeedDetailActivity.ViewPagerAdapter adapter = new FeedDetailActivity.ViewPagerAdapter(getSupportFragmentManager());
adapter.addFragment(new TabFragment_DetailFeed(), "DETAIL");
adapter.addFragment(new TabFragment_DetailComment(), "COMMENT");
adapter.addFragment(new TabFragment_DetailImage(), "IMAGE");
adapter.addFragment(new TabFragment_DetailSurvey(), "SURVEY");
viewPager.setAdapter(adapter);
}
#Override
public void sendArray(ArrayList<String> strings) {
TabFragment_DetailImage frag = (TabFragment_DetailImage)
getSupportFragmentManager().findFragmentById();
frag.method(strings);
}
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);
}
}
}
You should try to use EventBus. With it you can register receivers in your fragments and post events from any part of code.
Here is a little example for your fragments:
In C fragment override onResume() and onPause() like this
#Override
public void onResume() {
super.onResume();
EventBus.getDefault().register(this);
}
#Override
public void onPause() {
super.onPause();
EventBus.getDefault().unregister(this);
}
And also subscribe to your event (you need to create class for it)
#Subscribe(threadMode = ThreadMode.MAIN)
public void onResult(OnResultEvent event) {
//do stuff in event
}
Then in B fragment do like this
public void doStuff(){
//do stuff here
EventBus.getDefault().post(new OnResultEvent(result));
}
You Activity implements your interface(ArrayPasser) in this case which is defined in FragmentA
public class YourActivity implements FragmentA.ArrayPasser{
#Override
public void sendArray(ArrayList<String> strings){
// Get instance of Fragment B using FragmentManager
FraB frag = (FragB)
getSupportFragmentManager().findFragmentById(R.id.fragment_b);
frag.someMethod(strings); //passing arraylist to Fragment B from
Activity
}
}
// Fragment A defines an Interface, and calls the method when needed
public class FragA extends Fragment{
ArrayPasser mCallback; //interface reference
public interface ArrayPasser{
public void sendArray(ArrayList<String> strings);
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
// This makes sure that the container activity has implemented
// the callback interface. If not, it throws an exception
try {
mCallback = (ArrayPasser) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement ArrayPasser");
}
}
public void someMethod(ArrayList<String>strings){
mCallback.sendArray(strings); //passing array list to fragment
}
#Override
public void onDetach() {
mCallback = null; // => avoid leaking
super.onDetach();
}
}
// Fragment B has a public method to do something with the Array
public class FragB extends Fragment{
public void method(ArrayList<String> strings){
// Here you have it
}
}
In my MainActivity, I have:
#Override
protected void onResume() {
super.onResume();
checkForCrashes();
checkForTutorial();
checkForUpdates();
setStore();
setup();
}
In setup(), I call initializeTabs() in a callback:
protected void setup() {
final Store s = getStore();
setBackground();
if (s == null) {
unauthorizedHandler();
return;
}
final Context mainActivity = this;
fragments = getTabFragments();
StoresController.getStoreDetails(s, mainActivity, new Callback<StoreDetailDecorator>() {
#Override
public void success(StoreDetailDecorator storeDetailDecorator, Response response) {
s.prettyName = storeDetailDecorator.store.pretty_name;
s.save();
Log.v(TAG, s.prettyName);
TextView toolbar_label = (TextView)findViewById(R.id.toolbar_label);
toolbar_label.setText(MainActivity.getTruncatedMenuName(s.name()));
SummaryTab t1 = (SummaryTab)fragments.get(0);
t1.notifier = (SummaryTabLoadingNotifier)mainActivity;
initializeTabs(s, fragments);
t1.populateReport();
}
}
}
public void initializeTabs(Store s, List<Fragment> fragments ) {
ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager(), getTabTitles(), fragments);
ViewPager pager = (ViewPager) findViewById(R.id.pager);
pager.setOffscreenPageLimit(2);
pager.setAdapter(adapter);
}
That last line is crashing for some customers.
java.lang.IllegalStateException: Fragment InfoTab{1bcb80f} is not currently in the FragmentManager
But not every time. Why would this happen sometimes? Something to do with the fragment not being connected? I read some things about checking isAdded() on a fragment, but that's for checking if a fragment is added to an Activity. I'm using a FragmentStatePagerAdapter :
public class ViewPagerAdapter extends FragmentStatePagerAdapter {
private CharSequence[] titles;
private List<Fragment> fragmentList = new ArrayList<>();
public ViewPagerAdapter(FragmentManager fragmentManager, CharSequence titles[], List<Fragment> fragmentList) {
super(fragmentManager);
this.titles = titles;
this.fragmentList = fragmentList;
}
#Override
public android.support.v4.app.Fragment getItem(int position) {
return fragmentList.get(position);
}
#Override
public CharSequence getPageTitle(int position) { return titles[position]; }
#Override
public int getCount() { return fragmentList.size(); }
#Override
public Parcelable saveState() {
return null;
}
}
Could saveState(){ return null;} be it? This is there, as I understand things, to ensure the view is refreshed every time.
onResume() is called every time your activity returns to foreground.
If one of your users, for example, presses the home button and returns to your app then getStoreDetails() will be called again and you'll create a new adapter (with the same old fragment list) when the result arrives.
You should instantiate your fragments, create an adapter and populate your viewpager with the adapter only once (onCreate() would be the spot).
When new data arrives from getStoreDetails() just update the already added fragments with the new data.
This is because you are returning null in saveState(). You shouldn't try to override this behavior.
But even if you want to do it for some reason, you have to override public void restoreState(Parcelable state, ClassLoader loader) as well to avoid crash, because that method is relying on data saved in saveState().
But I would suggest you to not override it at all, and instead explain what you wanted to achieve there.
I have a viewpager in my activity. Inside the viewpager, there is a fragment and the fragment contains recyclerview. Once a notification is received, I want to add the new item in my recyclerview and want to highlight it as well.
Activity class:
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
boolean not_id = intent.getBooleanExtra(AppConstants.NEW_NOTIFICATION, false);
String bid_id = intent.getStringExtra(AppConstants.BID_NOTIFICATION_ID);
if(not_id){
ActiveBidFragment frag = ActiveBidFragment.newInstance(bid_id, "");
frag.setBid_id(bid_id);
frag.newBidReceived();
frag.setBid_id("0");
Log.i(TAG,"~~~~done refreshing");
}
}
Fragment:
public void newBidReceived(){
fetchActiveBids();
}
private void fetchActiveBids(){
if(mActiveBidPresenter == null)
mActiveBidPresenter = new ActiveBidPresenterImpl(this);
mActiveBidPresenter.getActiveBids();
}
#Override
public void onFetchedActiceBidsSuccess() {
if(bids == null)
bids = new ArrayList<ActiveBid>();
bids.clear();
bids.addAll(AppContext.getInstance().getActiveBids());
adapter.notifyDataSetChanged();
}
Adapter class:
#Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
Log.i(TAG, "~~~~on Bind Holder");
String bid_id = ((ActiveBidFragment) mListener).getCurrentBidId();
List<Bid> bids = mActiveBids.get(position).getBid();
The presenter class calls a method to show dialog,which is:
Presenter Class:
#Override
public void getActiveBids() {
mActiveBidView.showProgressBar(AppConstants.FETCHING_ACTIVE_BIDS);
String vendor_id = Preferences.getActiveInstance(null).getVendor_id();
mActiveBidInteractor.fetchActiveBids(vendor_id, this);
}
#Override
public void showProgressBar(String msg) {
if(mProgressBar != null && mProgressBar.isShowing())
mProgressBar.dismiss();
mProgressBar = CodeUtil.generateWaitingDialog(getActivity(), msg);
mProgressBar.show();
}
#Override
public void fetchedActiveBidSuccessfully(JSONObject response) {
try{
Gson gson = new Gson();
ActiveBidResponse resp = gson.fromJson(response.toString(), ActiveBidResponse.class);
String status = resp.getStatus();
if(status.equals(AppConstants.LOGIN_SUCCESS)){
List<ActiveBid> activeBids = resp.getData();
AppContext.getInstance().setActiveBids(activeBids);
//AppContext.getInstance().setFetchNewActiveBids(false);
mActiveBidView.onFetchedActiceBidsSuccess();
}else{
mActiveBidView.onFetchedActiveBidsFailed();
}
}catch (Exception ex){
mActiveBidView.onFetchedActiveBidsFailed();
}
finally {
mActiveBidView.hideProgressBar();
}
}
Interactor Class:
#Override
public void fetchActiveBids(String vendor_id, OnActiveBidFinished mListener) {
String url = AppConstants.ACTIVE_BID_URL;
Map<String,String> params = new HashMap<String, String>();
params.put(AppConstants.VENDOR_ID, vendor_id);
JsonObjectRequest loginRequest = new JsonObjectRequest(Request.Method.POST,
url,
new JSONObject(params),
createMyReqSuccessListener(mListener),
createMyReqErrorListener(mListener));
VolleySingleton.getRequestQueue().add(loginRequest);
}
Dialog Class:
public static ProgressDialog generateWaitingDialog(Context context, String message){
ProgressDialog progressDialog = new ProgressDialog(context, AlertDialog.THEME_HOLO_LIGHT);
progressDialog.setCancelable(false);
progressDialog.setMessage(message);
return progressDialog;
}
In dialog, I get error as a nullpointerexception, it shows getActivity as null.
Is there some other way I can achieve what I am trying to achieve, may be like recreating the whole instance of the activity if the activity already exists
Update:
Changed the fragment creation to this:
ActiveBidFragment frag = (ActiveBidFragment) adapter.getItem(0);
frag.setBid_id(bid_id);
frag.newBidReceived();
frag.setBid_id("0");
//adapter is the viewpagerpadapter to which fragment is attached
Your fragment will get the getActivity() always null, unless your fragment is attached with the activity.
In your case:
ActiveBidFragment frag = ActiveBidFragment.newInstance(bid_id, "");
frag.setBid_id(bid_id);
frag.newBidReceived();
frag is not attach with any activity.
I am maintaining the fragment instance in a hashmap inside my fragmentpageradapter and then I am referncing it in my onNewIntent. That's the only solution I could get. Its like a singleton pattern, till the activity is alive. If someone postes better solution, I would seriously like to know it
I am new to parcelable and I am trying to pass data from an Activity (MainActivity) to a fragment (MainFragment) but I`m struggle to get this right.
I made a class (InfoBean) with all the (parcelable) data. When I send the data from the MainActivity, the data from bean.newTheme (2131296447) is there but as soon as I try to retrieve in the Fragment, the value is 0!
Could someone pls have a look, what I`m doing wrong? Thank you for your help.
Send data (MainActivity):
public class MainActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener {
InfoBean bean = new InfoBean();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
SecureSharedPreferences theme = SecureSharedPreferences.getInstance(this, "MyPrefsFile");
int newTheme = theme.getInt("themeCustom", 0);
bean.newTheme = newTheme;
Bundle bundle = new Bundle();
bundle.putInt("theme", bean.newTheme); // debug shows value 2131296447
MainFragment mf = new MainFragment();
mf.setArguments(bundle);
//
}
}
Retrieve data (MainFragment):
public class MainFragment extends Fragment {
InfoBean bean = new InfoBean();
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
//
Bundle bundle = this.getArguments(); // Debugging shows 0!
if (bundle != null) {
bean.newTheme = bundle.getInt("theme");
}
if (bean.newTheme == 2131296447) { // White Theme
mCardView1.setBackgroundColor(Color.parseColor("#E8EBED"));
} else { // Dark Theme
mCardView1.setBackgroundColor(Color.parseColor("#282929"));
relLay.setBackgroundColor(Color.parseColor("#1B1C1C"));
}
return rootView;
}
}
InfoBean.class:
public class InfoBean implements Parcelable {
public int newTheme;
public int THEME_DARK = R.style.DarkTheme;
public int THEME_LIGHT = R.style.LightTheme;
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(this.newTheme);
dest.writeInt(this.THEME_DARK);
dest.writeInt(this.THEME_LIGHT);
}
public InfoBean() {
}
protected InfoBean(Parcel in) {
this.newTheme = in.readInt();
this.THEME_DARK = in.readInt();
this.THEME_LIGHT = in.readInt();
}
public static final Parcelable.Creator<InfoBean> CREATOR = new Parcelable.Creator<InfoBean>() {
#Override
public InfoBean createFromParcel(Parcel source) {
return new InfoBean(source);
}
#Override
public InfoBean[] newArray(int size) {
return new InfoBean[size];
}
};
}
If you have embedded fragment in your XML you can't use the setArguments() like that in your program. It is better to use dynamic fragment creation.
There is a brief example in android developer website which can guide you: http://developer.android.com/reference/android/app/Fragment.html there is also another implementation when you have embedded fragments and how to process arguments with that.
There is also another resource here which may help you:
Set arguments of fragment from activity
In your activity, you are using .putInt("theme" .....) but in the fragment you call .getParcelable("theme"). You're getting 0 because you're attempting to get two different data types.
Update
Since you have your fragment embedded in xml, you can't pass values to fragment class. To that you need to make it excute through java code and remove that xml. Make fragment Transaction then it will work
Update
You should try retrieving values in onCreate method of fragment.
#overide
protect void onCreate(bundle onSavedInstance){
if (savedInstance != null) {
bean.newTheme = bundle.getInt("theme");
}
}
Try this
if (bundle != null) {
bean.newTheme = bundle.getInt("theme");
}
instead of
if (bundle != null) {
bean.newTheme = bundle.getParcelable("theme");
}
I have view pager. My viewpager contains 3 fragments. In the first fragment I have an AsyncTask class. I parsed JSON with AsyncTask and I can show it in listview. (everything is ok)
I have one problem AsyncTask which I have in the first fragment does not finish when I go to the next fragments. When I am in the second fragment my AsyncTask is also running. How can I write code to cancel my AsyncTask when viewpager's page changed?
This is my source (this is the first fragment source; another fragment source is the same but the only difference is the Server Url):
public class StradaChefs1 extends Fragment {
public static CustomerStatistic stat;
private ConnectionDetector con;
private AlertDialogManager alert = new AlertDialogManager();
#SuppressLint("ClickableViewAccessibility")
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.strada_chefs_1, container,
false);
stat = new CustomerStatistic();
con = new ConnectionDetector(getActivity());
if (!con.isConnectingToInternet()) {
alert.showAlertDialog(getActivity(),
"You have not internet connection");
} else {
stat.execute("my urlllllllll"); // geo
}
return rootView;
}
public class CustomerStatistic extends AsyncTask<String, Void, String> {
ProgressDialog pDialog;
#Override
protected void onPreExecute() {
super.onPreExecute();
pDialog = ProgressDialog.show(getActivity(), "Please Wait... ",
"Loading... ");
pDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
pDialog.setCancelable(false);
pDialog.show();
}
#Override
protected String doInBackground(String... params) {
return Utils.getJSONString(params[0]);
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
try {
JSONArray mainJson = new JSONArray(result);
String first = mainJson.getString(0);
JSONObject jobject = new JSONObject(first);
String image = jobject.getString("image");
String String_title = jobject.getString("title");
String String_name = jobject.getString("name");
String String_desc = jobject.getString("description");
String second = mainJson.getString(1);
} catch (JSONException e) {
e.printStackTrace();
}
if (pDialog != null) {
pDialog.dismiss();
pDialog = null;
}
}
}
#Override
public void onResume() {
Log.e("DEBUG", "onResume of HomeFragment");
super.onResume();
}
#Override
public void onStop() {
super.onStop();
if (stat != null && stat.equals(AsyncTask.Status.RUNNING)) {
stat.cancel(true);
Toast.makeText(getActivity(), "finished", Toast.LENGTH_SHORT)
.show();
}
}
}
This is a viewpager java code
public class TabbedActivity1 extends Fragment {
private StradaChefs1 mfragment1;
private StradaChefs2 mfragment2;
private StradaChefs3 mfragment3;
private StradaChefs4 mfragment4;
SectionsPagerAdapter mSe;
public static final String TAG = TabbedActivity1.class.getSimpleName();
ViewPager mViewPager;
private ArrayList<Fragment> fragmentList;
public static TabbedActivity1 newInstance() {
return new TabbedActivity1();
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.activity_item_one_1, container, false);
mSe=new SectionsPagerAdapter(getChildFragmentManager());
mViewPager = (ViewPager) v.findViewById(R.id.pager1);
CirclePageIndicator circle=(CirclePageIndicator)v.findViewById(R.id.circleindicator1);
mViewPager.setAdapter(mSe);
circle.setViewPager(mViewPager);
mfragment1 = new StradaChefs1();
mfragment2 = new StradaChefs2();
mfragment3 = new StradaChefs3();
mfragment4 = new StradaChefs4();
fragmentList = new ArrayList<Fragment>();
fragmentList.add(mfragment1);
fragmentList.add(mfragment2);
fragmentList.add(mfragment3);
fragmentList.add(mfragment4);
mViewPager.setPageTransformer(false, new PageTransformer() {
#Override
public void transformPage(View page, float position) {
page.setRotationY(position * -40);
}
});
return v;
}
public class SectionsPagerAdapter extends FragmentPagerAdapter {
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
return fragmentList.get(position);
}
#Override
public int getCount() {
return 4;
}
#Override
public CharSequence getPageTitle(int position) {
return null;
}
}
}
How can I solve this problem?
The FragmentPagerAdapter keeps additional fragments, besides the one shown, in resumed state, so you can't use onPause and onResume for starting/stopping the AsyncTask. The solution is to implement a custom OnPageChangeListener and create a new method for when the fragment is shown.
1) Create LifecycleManager Interface The interface will have two methods and each ViewPager’s Fragment will implement it. These methods Are as follows:
public interface FragmentLifecycle {
public void onPauseFragment();
public void onResumeFragment();
}
2) Let each Fragment implement the interface
3) Implement interface methods in each fragment - in onPauseFragment stop the AsyncTask, in onResumeFragment start it
4) Call interface methods on ViewPager page change You can set OnPageChangeListener on ViewPager and get callback each time when ViewPager shows another page
5) Implement OnPageChangeListener to call your custom Lifecycle methods
Listener knows the new position and can call the interface method on new Fragment with the help of PagerAdapter. I can here call onResumeFragment() for new fragment and onPauseFragment() on the current one.
I need to store also the current fragment’s position (initially the current position is equal to 0), since I don’t know whether the user scrolled from left to right or from right to left. See what I mean in code:
private OnPageChangeListener pageChangeListener = new OnPageChangeListener() {
int currentPosition = 0;
#Override
public void onPageSelected(int newPosition) {
FragmentLifecycle fragmentToShow = (FragmentLifecycle)pageAdapter.getItem(newPosition);
fragmentToShow.onResumeFragment();
FragmentLifecycle fragmentToHide = (FragmentLifecycle)pageAdapter.getItem(currentPosition);
fragmentToHide.onPauseFragment();
currentPosition = newPosition;
}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2) { }
public void onPageScrollStateChanged(int arg0) { }
};
I didn't write the code. Full tutorial here
When you start the asynctask set the flag isRunning=true
when you are trying to jump from one fragment to other it mean
as per fragment lifecycle your are pausing and stoping your current fragment
so in onStop method of fragment you can check isRunning flag of asynctask is true if yes the
cancel the asyntask
its my logic hope it will help you to achieve your requirement