0

Actually, i created a navigation drawer that has three items and on clicking on every item it goes to its fragment that displays certain type of products , so i have an Activity with three fragments for each type of them.

If i would like to add another product type i will have to create its fragment. So ,My question is , are there any methods that can only make one fragment and every time an item is clicked only the data inside the fragment to be changed/replaced and not to replace the whole fragment itself with another ?

Edited my main activity:

public class MainActivity extends AppCompatActivity {


Toolbar toolbar;

DrawerLayout drawerLayout;

RecyclerView recyclerView;

String navTitles[];
private NavigationView navigationView;
TypedArray navIcons;

RecyclerViewAdapter recyclerViewAdapter;

ActionBarDrawerToggle drawerToggle;
Fragment[] fFragments = new Fragment[3];

@Override

protected void onCreate(Bundle savedInstanceState) {


    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_main);

    //Let's first set up toolbar

    setupToolbar();

    //Initialize Views

    recyclerView = (RecyclerView) findViewById(R.id.recyclerView);

    drawerLayout = (DrawerLayout) findViewById(R.id.drawerMainActivity);


    //Setup Titles and Icons of Navigation Drawer

    navTitles = getResources().getStringArray(R.array.navDrawerItems);

    navIcons = getResources().obtainTypedArray(R.array.navDrawerIcons);

    recyclerViewAdapter = new RecyclerViewAdapter(navTitles, navIcons, this);

    recyclerView.setAdapter(recyclerViewAdapter);


    recyclerViewAdapter.setClickedListener(new RecyclerViewAdapter.ClickListerner() {

        @Override

        public void onItemlistener(int index) {

            updateUIWithIndex(index);

        }

    });


    recyclerView.setLayoutManager(new LinearLayoutManager(this));
    //Finally setup ActionBarDrawerToggle

    setupDrawerToggle();


    //Add the Very First  Fragment to the Container

    updateUIWithIndex(1);


}



// on click update fragment
private void updateUIWithIndex(int index) {


    drawerLayout.closeDrawers();


    FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();

    Fragment fFragment = null;


    if (fFragments[index - 1] == null) {

        switch (index) {

            case 1:

                fFragment = new FirstFragment();

                break;

            case 2:

                fFragment = new SecondFragment();

                break;

            case 3:

                fFragment = new ThirdFragment();

                break;

        }

        fFragments[index - 1] = fFragment;

    } else {

        fFragment = fFragments[index - 1];

    }

    fragmentTransaction.replace(R.id.containerView, fFragment);

    fragmentTransaction.commit();


}


void setupToolbar() {

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

    setSupportActionBar(toolbar);

    getSupportActionBar().setDisplayShowHomeEnabled(true);

}


void setupDrawerToggle() {

    drawerToggle = new ActionBarDrawerToggle(this, drawerLayout, toolbar, R.string.app_name, R.string.app_name);

    //This is necessary to change the icon of the Drawer Toggle upon state change.

    drawerToggle.syncState();

}


}   

My Fragment :

public class FirstFragment extends Fragment implements ClickListner  {

private final String LOG_TAG = FirstFragment.class.getSimpleName();
private DisplayAdapter recyclerViewAdapter;
private RecyclerView recyclView;
private ArrayList<Products> pProduct = null;

private List<Products> prods = null;
ProductDbHelper pDB;
ProgressDialog mJsonDialog;


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

    View myView = inflater.inflate(R.layout.all_products, container, false);
    pDB = new ProductDbHelper(getActivity());
    mJsonDialog = new ProgressDialog(getActivity());
    mJsonDialog.setIndeterminate(true);


    if (pDB.isDataAvailable() == 0) {
        mJsonDialog.setMessage("Parsing JSON feed...");
        mJsonDialog.show();
        getFeed();

    } else {

        new FetchDatabaseTask().execute();
    }


    return myView;
}


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

    recyclView = (RecyclerView) view.findViewById(R.id.RecycleList);


    StaggeredGridLayoutManager layoutManager = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL);

    recyclView.setLayoutManager(layoutManager);

    recyclerViewAdapter = new DisplayAdapter(getActivity(), new ArrayList<Products>());
    recyclView.setAdapter(recyclerViewAdapter);
    recyclerViewAdapter.setClickListener(this);


}

@Override
public void itemClicked(View view, Parcelable product) {

    Intent intent = new Intent(getActivity(), DetailActivity.class);
    intent.putExtra("P", product);
    startActivity(intent);

}

public void getFeed() {

    RestInterface interfaces = Client.getClient().create(RestInterface.class);

    Call<List<Products>> call = interfaces.getProductsReport();
    call.enqueue(new Callback<List<Products>>() {

        @Override
        public void onResponse(Call<List<Products>> call, Response<List<Products>> response) {

            prods = response.body();


            for (int i = 0; i < prods.size(); i++) {
                pDB.addShop(prods.get(i));
            }

            new FetchDatabaseTask().execute();

            if (mJsonDialog.isShowing())
                mJsonDialog.dismiss();

        }

        @Override
        public void onFailure(Call<List<Products>> call, Throwable t) {

            Log.e(LOG_TAG, "FFFF" + t.toString());
        }
    });

}


public class FetchDatabaseTask extends AsyncTask<Void, Void, List<Products>> {


    protected void onPreExecute() {
        mJsonDialog.setMessage("Reading from internal storage...");
        mJsonDialog.show();

    }

    @Override
    protected List<Products> doInBackground(Void... voids) {

       // get all the shop's products
        List<Products> lProduct = pDB.getAllShops();

      // in the second fragment , sort the products' price in ascending order
         List<Products> lProduct = pDB.sortShopsAscend();


       // in the third fragment sort the products descendingly 
          List<Products> lProduct = pDB.sortShopsDescend();

        return lProduct;
    }


    protected void onPostExecute(List<Products> shops) {
        super.onPostExecute(shops);
        if (shops != null) {
            if (recyclerViewAdapter != null) {
                recyclerViewAdapter.setData(shops);
            } else {
                pProduct = new ArrayList<>();
                pProduct.addAll(shops);
            }
        }


        if (mJsonDialog.isShowing())
            mJsonDialog.dismiss();
    }
}


}
Suzy
  • 1
  • 4

2 Answers2

1

Make those changes in the MainActivity class :

public class MainActivity extends AppCompatActivity {  

Toolbar toolbar;    
DrawerLayout drawerLayout;    
RecyclerView recyclerView;    
String navTitles[];
private NavigationView navigationView;
TypedArray navIcons;    
RecyclerViewAdapter recyclerViewAdapter;    
ActionBarDrawerToggle drawerToggle;<

//If you want to use the first fragment only
FirstFragment fragment = null;
.
.
.
recyclerViewAdapter.setClickedListener(new RecyclerViewAdapter.ClickListerner() {

    @Override

    public void onItemlistener(int index) {
        //Call this method to close the drawer layout or you can simply call the close method here
        updateUIWithIndex(index);

        //Do something depending on the index
        if(index == 0){
            //Call getFeed() for example
            fragment.getFeed();
        }
        else if(index == 1){
            //call another method
        }
    }
});
.
.
.

// on click update fragment
//I don't know if you still need the index in this method
private void updateUIWithIndex(int index) {    
    //Close the drawer Layout anyway
    drawerLayout.closeDrawers();     

    if (fragment == null) {
       FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
       //Create an instance of the FirstFragment
       fragment = new FirstFragment();
       fragmentTransaction.replace(R.id.containerView, fragment);    
       fragmentTransaction.commit();     
    }


}
Rachik Abidi
  • 156
  • 8
  • setArguments can only be called before the Fragment is attached to the Activity, though, so this approach doesn't quite answer how to change the displayed data at a later point – OneCricketeer Sep 06 '16 at 14:17
  • Suzy is asking if multiple navigation drawer items can lead to the same layout but with different loaded data, so my solution was to send a tag or something through the arguments before the `FragmentManager`is called. Then, using the `onCreateView()`method, the arguments could be retrieved and the data will vary depending on the passed arguments. I don't know if what I understood was clear :) – Rachik Abidi Sep 06 '16 at 14:30
  • Right, that'll work, but only if replacing the Fragment and setting new arguments each time a list item is clicked. Because the Fragment is otherwise attached to the Activity, therefore calling setArguments again won't do anything. – OneCricketeer Sep 06 '16 at 14:37
  • Yes, of course, the old fragment will be destroyed and replaced with a new instantiation of the same fragment with different arguments :) – Rachik Abidi Sep 06 '16 at 14:41
  • But if you read the last part of the question, that isn't wanted – OneCricketeer Sep 06 '16 at 14:43
  • Ah okay, I got it! So, dealing with items is only for changing some content in the loaded fragment. Then, the answer below can solve the problem if the fragment is loaded succesfully, but this needs a global variable to hold the instantiation of the fragment! What do you think? – Rachik Abidi Sep 06 '16 at 14:52
  • yes , that what i meant , change the content in the loaded fragment without replacing or having a new one. i just want to retrieve different data and process it only one time , as no need to repeat the same code again three times, do u got what i mean ? – Suzy Sep 06 '16 at 15:02
  • @Suzy yes, I got it! Use the code written in the answer below, but use a global variable for your Fragment instance, and do not call the FragmentManager each time you click on an item if the fragment is already loaded. Did you get what I mean? I can edit my answer if you want that :) – Rachik Abidi Sep 06 '16 at 15:08
  • @Suzy, can you share your Activity code so that I can tell you where to do the changes exactly? – Rachik Abidi Sep 06 '16 at 17:27
  • @RachikAbidi , i added my main activity and fragment , kindly check them – Suzy Sep 07 '16 at 08:42
  • @Suzy check the updates in my answer, tell me if that helps :) – Rachik Abidi Sep 07 '16 at 09:47
  • 1
    Nice ^_^ , just mark it as an answer, so that anyone who has the same need as you, can follow this code! – Rachik Abidi Sep 07 '16 at 12:26
0

You can simply pass variable to Fragment method.

Completely updated post

In your case:

set fragment as field in your MainActivity

private FirstFragment firstFragment;

Run this fragment in your OnCreate method in MainActivity

FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
firstFragment = null;
firstFragment = new FirstFragment();
fragmentTransaction.replace(R.id.containerView, firstFragment );
fragmentTransaction.commit();

Then replace updateUIWithIndex method to fragment method, so you have:

recyclerViewAdapter.setClickedListener(new RecyclerViewAdapter.ClickListerner() {
    @Override
    public void onItemlistener(int index) {
        firstFragment.getFeed(index)
    }
});

Pass index to getFeed:

public void getFeed(int index) {

final int currentIndex = index;

    RestInterface interfaces = Client.getClient().create(RestInterface.class);

Call<List<Products>> call = interfaces.getProductsReport();
call.enqueue(new Callback<List<Products>>() {

    @Override
    public void onResponse(Call<List<Products>> call, Response<List<Products>> response) {
        prods = response.body();
        for (int i = 0; i < prods.size(); i++) {
            pDB.addShop(prods.get(i));
        }
        new FetchDatabaseTask(currentIndex ).execute();
        if (mJsonDialog.isShowing())
            mJsonDialog.dismiss();
    }

    @Override
    public void onFailure(Call<List<Products>> call, Throwable t) {
        Log.e(LOG_TAG, "FFFF" + t.toString());
    }
});

Add constructor to FetchDatabaseTask class

public class FetchDatabaseTask extends AsyncTask<Void, Void, List<Products>> {

   private int currentIndex = 0;

   FetchDatabaseTask(int index) {
      currentIndex = index;
   }

   //ur others methods here
}

And then you can do as you need in onPreExecute,doInBackground and onPostExecute methods like this:

protected void onPostExecute(List<Products> shops) {
    super.onPostExecute(shops);

    switch (currentIndex) {
        case 0:
            if (shops != null) {
                if (recyclerViewAdapter != null) {
                    recyclerViewAdapter.setData(shops);
                } else {
                    pProduct = new ArrayList<>();
                    pProduct.addAll(shops);
                }
            }
            if (mJsonDialog.isShowing())
                mJsonDialog.dismiss();
            break;
        case 1:
            //ur SecondFragment code
            break;
        case 2:
            //ur ThirdFragment code
            break;
    }
}

So you can use only one fragment for every type of product or whatever you want.

Andrey Danilov
  • 6,194
  • 5
  • 32
  • 56
  • and if my fragment for example has those methods how should i inform it to deal with the doChanges ? public class MyFragment extends Fragment() { //my code public View onCreateView() public void getDataFromDatabase() public void doChanges(String something) { myTextView.setText(something); } } – Suzy Sep 06 '16 at 15:07
  • the question was about updating after navigation drawer click, right? What do you want to see after clicking drawer item? – Andrey Danilov Sep 06 '16 at 15:11
  • how will i implement my methods in the do changes ? i still didn't get how will i update the data in myFragment ? – Suzy Sep 06 '16 at 15:40
  • you have DrawerItemClickListener in your Activity, right? Just call method from your Fragment in your Activity. – Andrey Danilov Sep 06 '16 at 20:28
  • if you show me more your code I can post better example – Andrey Danilov Sep 06 '16 at 20:28
  • what is difference between First, Second and Third Fragment? – Andrey Danilov Sep 07 '16 at 09:01
  • the difference is in the FetchDatabaseTask , in the second fragment i sort the products with least price . – Suzy Sep 07 '16 at 09:40
  • That's Brilliant , Thanks alot ^_^ – Suzy Sep 07 '16 at 11:19