javaandroidandroid-fragmentsandroid-viewpagerfragment-oncreateview

Android Fragment with ViewPagers oncreateView Called in Wrong Fragment


I have a main activity which shows 3 fragments inside View Pagers with tabs.

mainActivity.java

public class mainActivity extends AppCompatActivity {

globalVariableActivity variable = new globalVariableActivity();

private APIService mAPIService;
private TextView mResponseTv;

private RecyclerView recyclerView;

private Token token = new Token("","","");

private Gson gson = new Gson();

private Context context=mainActivity.this;

private Toolbar toolbar;
private TabLayout tabLayout;
private ViewPager viewPager;

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

    //check if token is still active

    String current_token=token.getToken(context);

    MyFirebaseInstanceIDService Fcm= new MyFirebaseInstanceIDService();
    Fcm.onTokenRefresh(context,current_token);

    toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);

    getSupportActionBar().setDisplayHomeAsUpEnabled(false);

    viewPager = (ViewPager) findViewById(R.id.viewpager);
    setupViewPager(viewPager);

    tabLayout = (TabLayout) findViewById(R.id.tabs);
    tabLayout.setupWithViewPager(viewPager);

}

private void setupViewPager(ViewPager viewPager) {
    ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
    adapter.addFragment(new BeritaFragment(), "Berita");
    adapter.addFragment(new DiskusiFragment(), "Diskusi");
    adapter.addFragment(new PesanFragment(), "Pesan");
    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) {

        //Toast.makeText(context,"Item " + position + " shown.", Toast.LENGTH_SHORT).show();
        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) {
        Toast.makeText(context,"Position : " + position + " Title : "+ mFragmentTitleList.get(position) + " shown.", Toast.LENGTH_SHORT).show();
        return mFragmentTitleList.get(position);
    }
}

interface LyfecycleListener {
    void onCreatedView();
}

here's the first fragment code

beritaFragment.java

public class BeritaFragment extends Fragment {
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER

private APIService mAPIService = APIUtils.getAPIService();;
private Gson gson = new Gson();

private TextView createdAtText;
private TextView judulText;
private ImageView imageView;
private RecyclerView mRecyclerView;
private ListAdapter mListadapter;



private ArrayList<DataBerita> list_berita= new ArrayList<>();

private OnFragmentInteractionListener mListener;

public BeritaFragment() {
}

// TODO: Rename and change types and number of parameters
public static BeritaFragment newInstance(String param1, String param2) {
    BeritaFragment fragment = new BeritaFragment();

    return fragment;
}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    getBeritaTask getBerita= new getBeritaTask();
    try {
        Log.d("berita :", "On create 1");
        getBerita.execute().get(10000, TimeUnit.MILLISECONDS);

        Log.d("berita :", "On create 2");
    } catch (InterruptedException e) {
        e.printStackTrace();
    } catch (ExecutionException e) {
        e.printStackTrace();
    } catch (TimeoutException e) {
        e.printStackTrace();
    }

}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    View view = inflater.inflate(R.layout.fragment_berita, container, false);

    Log.d("Berita","On create view");

    Toast.makeText(getActivity() ,"Berita Fragment onCreateView", Toast.LENGTH_SHORT).show();


    ArrayList<DataBerita> data_berita;

    mRecyclerView = (RecyclerView) view.findViewById(R.id.recycler_view);
    judulText = (TextView)view.findViewById(R.id.summary_judul);
    createdAtText = (TextView)view.findViewById(R.id.created_at);
    //imageView = (ImageView)view.findViewById(R.id.gambar);

    final LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
    layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
    mRecyclerView.setLayoutManager(layoutManager);

    //data_berita=getBeritaList();

    Log.d("Berita","1");

    Log.d("Berita List : ", list_berita.toString());

    Log.d("Berita","3");
    mListadapter = new ListAdapter(list_berita);
    mRecyclerView.setAdapter(mListadapter);

    //Log.d("Berita view :", view.toString());
    return view;

}

public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
}

// TODO: Rename method, update argument and hook method into UI event
public void onButtonPressed(Uri uri) {
    if (mListener != null) {
        mListener.onFragmentInteraction(uri);
    }
}

public interface OnFragmentInteractionListener {
    // TODO: Update argument type and name
    void onFragmentInteraction(Uri uri);
}


public class ListAdapter extends RecyclerView.Adapter<ListAdapter.ViewHolder>
{
    private ArrayList<DataBerita> dataList;

    public ListAdapter(ArrayList<DataBerita> data)
    {
        this.dataList = data;
    }

    public class ViewHolder extends RecyclerView.ViewHolder
    {
        TextView judulText;
        TextView waktuText;
        ImageView gambarView;

        public ViewHolder(View itemView)
        {
            super(itemView);
            this.judulText = (TextView) itemView.findViewById(R.id.summary_judul);
            this.waktuText = (TextView) itemView.findViewById(R.id.created_at);
            //this.gambarView = (ImageView) itemView.findViewById(R.id.gambar);
        }
    }

    @Override
    public ListAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
    {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.berita_list_layout, parent, false);

        ViewHolder viewHolder = new ViewHolder(view);
        return viewHolder;
    }

    @Override
    public void onBindViewHolder(ListAdapter.ViewHolder holder, final int position)
    {
        Uri ImageURI=Uri.parse(dataList.get(position).getGambar_utama());
        holder.judulText.setText(dataList.get(position).getSummary_judul());
        holder.waktuText.setText(dataList.get(position).getCreated_at());
        //holder.gambarView.setImageURI(ImageURI);

        holder.itemView.setOnClickListener(new View.OnClickListener()
        {
            @Override
            public void onClick(View v)
            {
                Toast.makeText(getActivity(), "Item " + position + " is clicked.", Toast.LENGTH_SHORT).show();
            }
        });
    }

    @Override
    public int getItemCount()
    {
        return dataList.size();
    }
}


private class getBeritaTask extends AsyncTask<Void, Void, Void> {

    protected void onPreExecute() {
        Log.d("Berita","2.1");
    }

    protected Void doInBackground(Void... voids) {

        mAPIService.getBeritaList().enqueue(new Callback<Berita>() {
            @Override
            public void onResponse(Call<Berita> call, Response<Berita> response) {

                list_berita = new ArrayList<>();

                DataBerita data_berita = new DataBerita("","","","");

                String id_berita;
                String judul;
                String gambar_utama;
                String created_at;

                Log.d("Berita","2.2");
                if(response.isSuccessful()) {

                    Berita body = gson.fromJson(response.body().toString(),Berita.class);

                    for (int i = 0; i < body.getList_berita().getData().size(); i ++) {

                        id_berita=body.getList_berita().getData().get(i).getId_berita();
                        judul=body.getList_berita().getData().get(i).getSummary_judul();
                        gambar_utama=body.getList_berita().getData().get(i).getGambar_utama();
                        created_at=body.getList_berita().getData().get(i).getCreated_at();

                        data_berita = new DataBerita(id_berita,judul,gambar_utama,created_at);
                        list_berita.add(data_berita);
                    }
                    Log.d("Berita List",list_berita.toString());

                }else{
                    Log.d("Berita", "Fail");
                }

            }

            @Override
            public void onFailure(Call<Berita> call, Throwable t) {
                Log.d("Berita Fail", t.getMessage());
            }
        });

        return null;
    }
}

here's the 2nd and 3rd fragment (these 2 fragments are still mostly empty, with code for toast and log only for now)

DiskusiFragment.java

public class DiskusiFragment extends Fragment {
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";

// TODO: Rename and change types of parameters
private String mParam1;
private String mParam2;

private OnFragmentInteractionListener mListener;

public DiskusiFragment() {
    // Required empty public constructor
}

// TODO: Rename and change types and number of parameters
public static DiskusiFragment newInstance(String param1, String param2) {
    DiskusiFragment fragment = new DiskusiFragment();

    return fragment;
}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {

    Toast.makeText(getActivity() ,"Diskusi Fragment onCreateView", Toast.LENGTH_SHORT).show();

    return inflater.inflate(R.layout.fragment_diskusi, container, false);
}

// TODO: Rename method, update argument and hook method into UI event
public void onButtonPressed(Uri uri) {
    if (mListener != null) {
        mListener.onFragmentInteraction(uri);
    }
}

public interface OnFragmentInteractionListener {
    // TODO: Update argument type and name
    void onFragmentInteraction(Uri uri);
}
}

here's the problem,

fragment onCreateView function seems to be called on / in the wrong fragment.

when I start the app here's what happened :

  1. Item position 0 , 1, and 2 is called
  2. 1st fragment on create view is called, and 2nd fragment on create view is called immediately

what happens next, depends on what I do :

when I change from 1st fragment => 2nd fragment, 3rd fragment on create view is called

when I change from 1st fragment => 3rd fragment, 3rd fragment on create view is called

when I switch from 2nd fragment => 1st fragment, no fragment on create view called

when I switch from 2nd fragment => 3rd fragment, no fragment on create view called

when I switch from 3rd fragment => 2nd fragment, no fragment on create view called (or sometimes 1st fragment on create view is called)

when I change from 3rd fragment => 1st fragment, 1st fragment on create view called

is this what suppose (in regard to onCreateView function is called on the wrong fragment) to happen?

if not, where did I code wrong?

Thank you very much

*EDIT : this behaviour is normal, I'm really new to android. Very sorry for the inconvenience guys


Solution

  • The FragmentPagerAdapter keeps additional fragments, besides the one shown, in the resumed state.

    If you want to initialize stuff in the fragment you should do it when OnCreate is called.

    Anything that is related to the UI been loaded properly should happen on onViewCreated

    In addition, if you want to receive more information about how to handle fragments inside a ViewPager

    @Shreyas Shetty answered it really well on this thread