How to update fragment content from activity (viewpager)?
Asked Answered
M

3

18

I have a simple viewPager with two fragments. Each fragment contains a TextView. I would like to be able to update the text of the current textView displayed from the activity.

Activity :

public class MainActivity extends FragmentActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main_activity);

        ArrayList<Fragment> fragments = new ArrayList<Fragment>();
        fragments.add(Fragment.instantiate(this, Live.class.getName()));
        fragments.add(Fragment.instantiate(this, Hit.class.getName()));

        this.pagerAdapter = new MyPagerAdapter(getSupportFragmentManager(),fragments);

        ViewPager pager = (ViewPager) findViewById(R.id.viewpager);
        pager.setAdapter(pagerAdapter);
    }
}

Adapter :

public class MyPagerAdapter extends FragmentPagerAdapter {

    private final ArrayList<Fragment> fragments;

    public MyPagerAdapter(FragmentManager fm, ArrayList<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();
    }
}

Fragment :

public class Live extends Fragment {
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        return inflater.inflate(R.layout.live, container,false);
    }
}

XML Fragment :

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="fill_parent"
              android:layout_height="fill_parent">
    <TextView android:layout_height="fill_parent"
              android:layout_width="fill_parent"
              android:text="First Fragment"
              android:id="@+id/status"/>
</LinearLayout>

Each fragment have a TextView with the id "status". Updating the text view in onCreateView works. But how can i update the textView from anywhere in the activity ?

I have tried this without succes :

Fragment :

public class Live extends Fragment {    
    public TextView tv;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.live, container,false);
        tv = (TextView) view.findViewById(R.id.status);

        return view;
    }
}

Activity :

@Override
    protected void onResume() {
        super.onResume();
        Live frag = (Live) pagerAdapter.getItem(0);
        frag.tv.setText("Test 2");
    }

But it gives me a nullPointerException on tv, probably because the fragment is not yet inflated.

I already read the following questions without success :

Myungmyxedema answered 28/2, 2013 at 14:2 Comment(0)
A
7

In your MyPagerAdapter class, Android calls getItem(...) only if it wants to create new Fragments. So it's problematic to use references there instead you should instatiate the fragments.

Check this Answer support-fragmentpageradapter-holds-reference-to-old-fragments

Ashy answered 28/2, 2013 at 14:14 Comment(4)
This is 100% right. I have already made this same mistake as the OP. Do NOT keep your own array of Fragments. The FragmentManager in the FragmentPagerAdapter holds all of Fragments and manages saving and restoring their state. They can be referenced as well - #8785721.Crapulous
Ok did it using : tamsler.blogspot.fr/2011/10/… and second solution of tamsler.blogspot.fr/2011/11/… . But from what i have experienced it's not possible to access the fragment in on create or on resume in the activity right ?Myungmyxedema
It's probably not awailable/inflated at that time. Why don't you use the fragments own lifecycle?Ashy
As long as the ViewPager and FragmentPagerAdapter are created/connected, the Fragments should be created/resumed. I have been able to access them in both methods, I just always check if my fragment.isResumed() before trying to do anything with it. Honestly, the answer in the link I posted is much more elegant, as you can get your Fragments right out of the FragmentManager, no need to keep track yourself.Crapulous
E
4

I solved this issue like this, create the adapter like this

package com.yubraj.sample.adapter;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;

import com.yubaraj.sample.activities.RashiFragment;
import java.util.List;


public class PageSliderAdapter extends FragmentStatePagerAdapter {
    static String[] titleList = new String[] { "today",
            "this month", "this year" };
    List<String> rashi;
    // private static String TAG = "pagerscreenslider";

    public PageSliderAdapter(FragmentManager fm, List<String> rashiList) {
        super(fm);
        this.rashi = rashiList;
    }
    public void updateData(List<String> rashisList){
        rashi.clear();
        this.rashi = rashisList;
        notifyDataSetChanged();
    }
    @Override
    public int getItemPosition(Object object) {
        // TODO Auto-generated method stub
        return POSITION_NONE;
    }

    @Override
    public Fragment getItem(int position) {
        Fragment fragment = new RashiFragment();
        Bundle bundle = new Bundle();
        bundle.putString("RASHI", rashi.get(position));
        bundle.putInt("RASHI_TYPE", position);
        fragment.setArguments(bundle);
        return fragment;
    }

    @Override
    public int getCount() {
        return titleList.length;
    }

    @Override
    public String getPageTitle(int position) {
        return titleList[position];
    }


}

Then from Your activity

List<String> rashiCollection = getJSONFromDb(Dates);
adapter.updateData(rashiCollection);
Epilogue answered 8/7, 2015 at 12:9 Comment(1)
i have been trying this for quite some time now but whenever i call notifydatasetchanged it in turn calls the addOnTabSelectedListener which results in an infinite loopProportioned
G
2
@Override
    public int getItemPosition(Object object) {
    XXXFragment fragment = (XXXFragment) object;
        if(…condition){
    fragment.refresh(…);
    }
        return super.getItemPosition(object);
    }

override the above. when you call notifyDataSetChanged(), the above method's triggered. do your refresh as you can.

Girder answered 3/3, 2015 at 1:25 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.