简体   繁体   中英

I get exception when i pass data to third fragment but it works ok for passing data to the second fragment

i have a problem with my three fragments application when i go to pass data between them.

I use an interface to pass the values, viewpager for the fragments and i keep the fragments on a list in the mainActivity.java.The problem seems to be the instance of the fragments i guess.

On my mainFragment (fragment1.java)i have two buttons, one for sending data to the 2nd fragment and one to send data to 3rd fragment.

The application works, and the data are shown on the second fragment when i press the button.

I get an exception if i press the second button to send the data to the third fragment.

The data are transfered to the 3rd fragment as they should be, but i get an exception if press the second button before i go to the second fragment and return to the first again.

I dont know if i make myself clear, but it seems that is an instance error although frag1 and frag2 have the same code.

here is my code:

mainactivity.java

public class MainActivity extends FragmentActivity 
implements ICommunicator{

private String Importeddata;
private PagerAdapter mPagerAdapter;
private List<Fragment> fragments;
private ViewPager mpager;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.viewpager_layout);
    initialisePaging();
}


private void initialisePaging() {
    // TODO Auto-generated method stub
    fragments = new Vector<Fragment>();
    fragments.add(Fragment.instantiate(this, Fragment1.class.getName()));
    fragments.add(Fragment.instantiate(this, Fragment2.class.getName()));
    fragments.add(Fragment.instantiate(this, Fragment3.class.getName()));

    mPagerAdapter = new PagerAdapter(this.getSupportFragmentManager(), fragments);

    mpager = (ViewPager)findViewById(R.id.viewpager);
    mpager.setAdapter(mPagerAdapter);       
}


public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
}


@Override
//Interface method implementation
public void respond(String data,int frItem) {
    // TODO Auto-generated method stub
    switch(frItem)
    {
    case 1:
        /*
         * THIS WAY WORKS 1
         * Fragment2 fr2 =  (Fragment2)fragments.get(1);
        Toast.makeText(this, "you passed values"+data, Toast.LENGTH_SHORT).show();
        System.out.println("you passed values"+data);
        fr2.changeData(data);*/


        /* THIS WAY WORKS 2 
         * Fragment2 fr2=(Fragment2)getSupportFragmentManager().findFragmentByTag("android:switcher:"+R.id.viewpager+":1");  
           fr2.changeData(data);
        */

        /* THIS WAY WORKS 3
         * 
         */
        Fragment2 fr2=(Fragment2) mPagerAdapter.instantiateItem(mpager, 1);     
        fr2.changeData(data);
        break;
    case 2:
        /*
         * 1st way works, only if i first go to fragment 2 and return to firstfragment*/
        /*otherwise i get a nullpointer EXCEPTION */

        /*Fragment3 fr3 =  (Fragment3)fragments.get(2);
        Toast.makeText(this, "you passed values"+data, Toast.LENGTH_SHORT).show();
        System.out.println("you passed values"+data);
        fr3.changeData(data);*/

        /*2nd way  works, only if i first go to fragment 2 and return to firstfragment*/
        /*otherwise i get a nullpointer EXCEPTION */
        Fragment3 fr3=(Fragment3)getSupportFragmentManager().findFragmentByTag("android:switcher:"+R.id.viewpager+":2");  
        fr3.changeData(data);
    }

}
}

BELOW IS THE FRAGMENT1.JAVA which it has the two buttons

public class Fragment1 extends Fragment{

    Button btn1;
    Button btn2;
    ICommunicator icommunicator;

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        Log.e(getTag(), "onActivityCreated 1");

        icommunicator = (ICommunicator) getActivity();  

        btn1 = (Button) getActivity().findViewById(R.id.Btn_Send);
        btn1.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                Toast.makeText(getActivity(), "you pressed the button", Toast.LENGTH_LONG).show();
                icommunicator.respond("hello from Fragment 1",1);               
            }           
        });

        btn2 = (Button)getActivity().findViewById(R.id.Btn_Send2);
        btn2.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                Toast.makeText(getActivity(), "you pressed button 2", Toast.LENGTH_SHORT).show();
                icommunicator.respond("hello from fragment1 fragment 2",2);

            }
        });
    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        Log.e(getTag(), "onAttach 1");
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.e(getTag(), "onDestroy 1");
    }

    @Override
    public void onPause() {
        super.onPause();
        Log.e(getTag(), "onPause 1");
    }

    @Override
    public void onResume() {
        super.onResume();
        Log.e(getTag(), "onResume 1");
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        Log.e(getTag(), "onCreateView 1");
        if (container == null){
            return null;
        }
        return inflater.inflate(R.layout.fragment1_layout,
                container,false);
    }
    }

**below is the fragment2.java, the fragment that i send the btn1 message**

    public class Fragment2 extends Fragment{

    private String data;
    private TextView txt;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        Log.e(getTag(), "onCreateView 2");
        txt = (TextView) getActivity().findViewById(R.id.txt_importData);
        if (container == null){
            return null;
        }
        return inflater.inflate(R.layout.fragment2_layout,
                container,false);
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        Log.e(getTag(), "onActivityCreated 2");
        txt = (TextView) getActivity().findViewById(R.id.txt_importData);
        if (this.data == null)
            txt.setText("i wait value....");
        else
            txt.setText(this.data);
    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        Log.e(getTag(), "onAttach 2");
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.e(getTag(), "onDestroy 2");
    }

    @Override
    public void onPause() {
        super.onPause();
        Log.e(getTag(), "onPause 2");
    }

    @Override
    public void onResume() {
        super.onResume();
        Log.e(getTag(), "onResume 2");
    }

    public void changeData(String importdata){
        this.data = importdata;
        txt.setText(importdata);
    }
    }

below is the fragment3.java, the fragment that i send the btn2 message the data are sent to the fragment3.java , so far so good, but i get a nullpointer exception unless i have gone to the second fragment first and return to the first fragment and after that i press the second button, it seems that is something wrong with the view instance of the fragment.

public class Fragment3 extends Fragment{

private String data;
private TextView txt;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    Log.e(getTag(), "onCreateView 3");
    txt = (TextView) getActivity().findViewById(R.id.txt_fragment3);
    if (container == null){
        return null;
    }
    return inflater.inflate(R.layout.fragment3_layout,
            container,false);

}


@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    txt = (TextView) getActivity().findViewById(R.id.txt_fragment3);
    Log.e(getTag(), "onActivityCreated 3");
    if (this.data == null)
        txt.setText("i wait value....");
    else
        txt.setText(this.data);
}


@Override
public void onAttach(Activity activity) {
    super.onAttach(activity);
    Log.e(getTag(), "onAttach 3");
}


@Override
public void onDestroy() {
    super.onDestroy();
    Log.e(getTag(), "onDestroy 3");
}


@Override
public void onPause() {
    super.onPause();
    Log.e(getTag(), "onPause 3");
}


@Override
public void onResume() {
    super.onResume();
    Log.e(getTag(), "onResume 3");
}

public void changeData(String importdata){
    this.data = importdata;
    txt.setText(importdata);
}
}

if anyone can help me or tell his opinion i would appreciate it.

i need interface to communicate through fragments , that is the way fragments interact with each other, in your answer you suggest to pass the data from inside the clickListener if i am not mistake.

as for the setoffscreenPageLimit , can you tell me where i tell the code to cashe three pages or is it the way viewpager works to cache by default just three pages?

I added :

mpager.setOffscreenPageLimit(3);

and it works! thank you.

It only caches 3 pages. Itself, page on right and on left. Add this:

mpager.setOffscreenPageLimit(3); // You have 3 fragments

And you can just do this, instead of doing all of that:

btn1 = (Button) getActivity().findViewById(R.id.Btn_Send);
btn1.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            TextView txt = (TextView) getActivity().findViewById(R.id.txt_importData);
            txt.setText("whatever you want");             
        }           
    });

btn2 = (Button)getActivity().findViewById(R.id.Btn_Send2);
btn2.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            TextView txt = (TextView) getActivity().findViewById(R.id.txt_fragment3);
            txt.setText("whatever you want");
        }
    })

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM