3

I'm creating an app that gets data from an XML file from a website and pass these data to a Fragment.

I'm using an Action Bar, I have 3 tabs, and also with a ViewPager. The fragment contains a ListView, I pass the data using Bundle, I can get the passed data from the fragment correctly.

public Fragment getItem(int i){
  switch(i){
    case 0:
      Bundle b1= new Bundle();
      b1.putString("cat", "artufonews");
      Fragment f1 = new LoadFrag();
      f1.setArguments(b1);
      return f1;
    case 1:
      Bundle b2 = new Bundle();
      b2.putString("cat", "artufo");
      Fragment f2 = new LoadFrag();
      f2.setArguments(b2);
      return f2;
    case 2:
      Bundle b3 = new Bundle();
      b3.putString("cat", "artmyst");
      Fragment f3 = new LoadFrag();
      f3.setArguments(b3);
      return f3;
    default :
      return new LoadMee();
  }
}

LoadFrag is the fragment I have. I could the pass data correctly, however when I try to update the listview with mPager.getAdapter().notifyDataSetChanged(), those 3 tabs will show me the same list no matter what I do.

Below code is the fragments code:

public static class LoadFrag extends Fragment{
    String cat;
    boolean kl = false;
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){

        //new TestAsync().execute();
        View rootView = inflater.inflate(R.layout.listfrage, container, false);
        ListView viewer;
        String[] hell = (String[])list.toArray(new String[list.size()]);

        final String[] tots = (String[])links.toArray(new String[links.size()]);
        cat = getArguments().getString("cat");
        CustomLister lister = new CustomLister(getActivity(), hell, bmps);
        viewer = (ListView)rootView.findViewById(R.id.lister);
        viewer.setAdapter(lister);
        viewer.setOnItemClickListener(new AdapterView.OnItemClickListener() {

            public void onItemClick(AdapterView<?> parent, View view, int position, long id){
                Toast.makeText(getActivity(), "You clicked: item " + tots[position], Toast.LENGTH_SHORT).show();;

                Intent i = new Intent(getActivity(), Starter.class);
                i.putExtra("link", tots[position]);
                startActivity(i);
            }
        });
        return rootView;    
    }

    @Override
    public void setMenuVisibility(final boolean visible) {
        super.setMenuVisibility(visible);
        if (visible && kl == false) {
            getActivity().setTitle(cat);
            new TestAsync().execute();
            kl = true;
        }
    }

    class TestAsync extends AsyncTask<Void, Integer, String>
    {
        String TAG = getClass().getSimpleName();

        ProgressDialog dialog;
        protected void onPreExecute (){
            Log.d(TAG + " PreExceute","On pre Exceute......");

            dialog = new ProgressDialog(getActivity());
            dialog.setMessage("Loading content..");
            dialog.setIndeterminate(true);
            dialog.setCancelable(false);
            dialog.show();
        }

        protected String doInBackground(Void...arg0) {
            Log.d(TAG + " DoINBackGround","On doInBackground...");


            tasker(cat);

            return "You are at PostExecute";
        }

        protected void onProgressUpdate(Integer...a){
            Log.d(TAG + " onProgressUpdate", "You are in progress update ... " + a[0]);
        }

        protected void onPostExecute(String result) {
            Log.d(TAG + " onPostExecute", "" + result);
            dialog.dismiss();
            mPager.getAdapter().notifyDataSetChanged();
    }


    public void tasker(String tag)
    {
        try{
            URL url = new URL("http://www.skyovnis.com/test.xml");
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            DocumentBuilder db = dbf.newDocumentBuilder();
            Document doc = db.parse(new InputSource(url.openStream()));
            doc.getDocumentElement().normalize();

            NodeList nodeList = doc.getElementsByTagName(tag);



            for (int i = 0; i < nodeList.getLength(); i++) {

                Node node = nodeList.item(i);

                Element fstElmnt = (Element) node;
                NodeList nameList = fstElmnt.getElementsByTagName("title");
                Element nameElement = (Element) nameList.item(0);
                nameList = nameElement.getChildNodes();
                list.add(((Node)nameList.item(0)).getNodeValue());

                NodeList websiteList = fstElmnt.getElementsByTagName("link");
                Element websiteElement = (Element) websiteList.item(0);
                websiteList = websiteElement.getChildNodes();
                links.add(((Node) websiteList.item(0)).getNodeValue());

                NodeList imgLinks = fstElmnt.getElementsByTagName("linkp");
                Element imgElement = (Element) imgLinks.item(0);
                imgLinks = imgElement.getChildNodes();
                linksp.add(((Node) imgLinks.item(0)).getNodeValue());
            }

            bmps = new Bitmap[linksp.size()];
            String[] imgs = (String[])linksp.toArray(new String[linksp.size()]);
            for(int i = 0; i < linksp.size(); i++){
                URL urls = new URL(imgs[i]);
                bmps[i] = BitmapFactory.decodeStream(urls.openConnection().getInputStream());
            }

            org.jsoup.nodes.Document docs = Jsoup.connect("http://www.skyovnis.com/arecibo-message/").get();
            org.jsoup.select.Elements newsHeadlines =  docs.select("div.entry-content p");

            for(org.jsoup.nodes.Element ele : newsHeadlines){
                hello = hello + ele.text();
            }

        }
            catch(Exception e){
                System.out.println(e);
            }
    }
  }
}

Basically, from the data I pass, an AsyncTask will run and read from a xml file. The string I pass to the fragment is the tag for to find from the xml. All things works, except every tab show me the same list.

what am I doing wrong here?


EDIT

ViewPager adapter:

mAdapter = new MyAdapter(getSupportFragmentManager());

mPager = (ViewPager)findViewById(R.id.pager);
mPager.setAdapter(mAdapter);

mPager.setOnPageChangeListener(
   new ViewPager.SimpleOnPageChangeListener() {
         @Override
         public void onPageSelected(int position) {
           // When swiping between pages, select the
           // corresponding tab.
           getActionBar().setSelectedNavigationItem(position);
         }
});

My CustomLister Class,

    package com.ovnis.skybeings;

import java.net.URL;
import java.util.List;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;

public class CustomLister extends ArrayAdapter<String>{

    private final Activity context;
    private final String[] web;
    private final Bitmap[] bmps;

    public CustomLister(Activity context, String[] web, Bitmap[] bmps){

        super(context, R.layout.list_compon, web);

        this.context = context;
        this.web = web;
        this.bmps = bmps;
    }

    @Override
    public View getView(int pos, View view, ViewGroup parent){
        LayoutInflater inflater = context.getLayoutInflater();
        View rowView = inflater.inflate(R.layout.list_compon, null, true);
        TextView txtTitle = (TextView)rowView.findViewById(R.id.txt);

        ImageView imageView = (ImageView)rowView.findViewById(R.id.img);
        txtTitle.setText(web[pos]);

        imageView.setImageBitmap(bmps[pos]);
        return rowView;
    }
}

Myadapter,

public static class MyAdapter extends FragmentPagerAdapter{
    public MyAdapter(FragmentManager fm){
        super(fm);
    }

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

    @Override
    public Fragment getItem(int i){
        switch(i){
        case 0:
            return new LoadMee();
        case 1:
            return new LoadFrag().newInstance("artufonews");
        case 2:
            return new LoadFrag().newInstance("artifos");
            default :
                return new LoadMee();
        }
    }

    @Override
    public int getItemPosition(Object object) {
        return POSITION_NONE;
    }

}
Aimkiller
  • 263
  • 1
  • 5
  • 13
  • that is because you don't catch the bundle that you have sent before. – ישו אוהב אותך Oct 07 '16 at 03:40
  • @ישואוהבאותך no that can't be. you can see my setMenuVisibility code? whenever I choose the tab, it will set my app title to the string that got passed to the fragment. It also works correctly, it changes my title too. the only problem is all of the tabs show me is the same list – Aimkiller Oct 07 '16 at 03:46
  • Okay, I was wrong. I don't see your `cat = getArguments().getString("cat"); ` previously. Could be because you don't set `CustomLister lister = new CustomLister(getActivity(), hell, bmps);` to your category? – ישו אוהב אותך Oct 07 '16 at 03:57
  • Hi can you show the code for your `ViewPager`'s adapter? – Weizhi Oct 07 '16 at 05:09
  • You are still not showing your `ViewPager`'s adapter code. I need to see your `MyAdapter` class. You are calling `mPager.getAdapter().notifyDataSetChanged();` to notify `MyAdapter` that data set has changed. Notifying `MyAdapter` alone does not magically change your views. I need to know how you are implementing `MyAdapter`. – Weizhi Oct 07 '16 at 08:53
  • @Weizhi sorry, i posted it now – Aimkiller Oct 07 '16 at 09:08

2 Answers2

3

You need to catch the Bundle that you've sent before. Doing something like below maybe can address your problem:

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

  Bundle bundle = this.getArguments();
  if (bundle != null) {
    yourStringData= bundle.getString("cat", "DEFAULT_VALUE");
    setupYourUIWithTheData(yourStringData);
  } else {
      Log.d(TAG, "bundle null");
  }
}

private void setupYourUIWithTheData(String yourData) {
  // Process the received data here.
  // Show all related with the data here.
}

--- UPDATE ---

To pass a value to a Fragment, a recommend ways is by adding a static method to your Fragment, like:

public static LoadFrag newInstance(String category) {
  LoadFrag fragment = new LoadFrag ();
  Bundle bundle = new Bundle();
  bundle.putString("cat", category);
  fragment.setArguments(bundle);
  return fragment;
}

Then you can call it simply by:

LoadFrag.newInstance("your_category");
ישו אוהב אותך
  • 28,609
  • 11
  • 78
  • 96
1

What went wrong:

In your MyAdapter's getItemPosition() method, you are returning POSITION_NONE. This means that whenever you call MyAdapter#notifyDataSetChanged() you will recreate all the fragments in your ViewPager. You can verify this behavior by adding a log message in your LoadFrag#onCreateView().

public static class LoadFrag extends Fragment{
    ...
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
    // Add a Log message here to verify
    Log.d("LoadFrag", "In onCreateView");

        ...
    }

    ...
}

Notice that onCreateView() is called every time after your AsyncTask completes. You are basically recreating LoadFrag after your AsyncTask completes and showing the initial state of your ListView.

How to fix it

Add a method in your CustomLister to update your data.

public class CustomLister extends ArrayAdapter<String>{
    ...
    public void updateData(String[] newWeb, Bitmap[] newBmps){
        web = newWeb;
        bmps = newBmps;
        notifyDataSetChanged();
    }
    ...
}

In your AsyncTask, get a reference of your CustomLister and call lister.updateData() with the new set of data instead of calling mPager.getAdapter().notifyDataSetChanged(),

Weizhi
  • 1,027
  • 8
  • 22