Search code examples
androidjsonandroid-asynctaskfragmentandroid-listfragment

Pass Asynctask JSON result to ListFragment


I have a ListFragment I need to show list items in it. But I guess I cannot pass my list from AsyncTask to ListFragment. Here is my code.

FragmentTwo.java

package com.apitech.sitebilgi;
import ...

public class FragmentTwo extends ListFragment {

    public FragmentTwo (){}

    private ProgressDialog pDialog;
    // JSON Node Names
    private static final String TAG_SITELER = "Siteler";
    private static final String TAG_SITE_ID = "siteid";
    private static final String TAG_SITE_URL = "siteurl";
    private static final String TAG_DIL = "dil";

    // Siteler ListView
    ListView sitelerLV = null;

    // siteler JSONArray
    JSONArray siteler = null;

    // Hashmap for ListView
    ArrayList<HashMap<String, String>> siteList;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_layout_two, container, false);
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onActivityCreated(savedInstanceState);

        siteList = new ArrayList<HashMap<String, String>>();
        sitelerLV = getListView();
        new GetSiteler().execute();

    }

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

        @Override
        protected void onPreExecute() {
            // TODO Auto-generated method stub
            super.onPreExecute();

            // Showing progress dialog
            pDialog = new ProgressDialog(getActivity());
            pDialog.setMessage("Siteleriniz Yükleniyor...");
            pDialog.setCancelable(false);
            pDialog.show();
        }

        @Override
        protected Void doInBackground(Void... params) {
            // TODO Auto-generated method stub

            final Thread t = new Thread (new Runnable() {

                @Override
                public void run() {
                        HttpClient httpclient = new DefaultHttpClient();
                        HttpPost httppost = new HttpPost(getResources().getString(R.string.site_fetch_url) + "?");

                        List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
                        nameValuePairs.add(new BasicNameValuePair("request", "sites"));
                        nameValuePairs.add(new BasicNameValuePair("userid", "24"));

                        httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs,
                                "UTF-8"));

                        HttpResponse response = httpclient.execute(httppost);
                        HttpEntity entity = response.getEntity();
                        final String siteYanit = EntityUtils.toString(entity);
                        JSONObject jsonObj = new JSONObject(siteYanit);
                        siteler = jsonObj.getJSONArray(TAG_SITELER);

                        for (int i=0; i<siteler.length(); i++) {
                            JSONObject s = siteler.getJSONObject(i);

                            String id = s.getString(TAG_SITE_ID);
                            String siteurl = s.getString(TAG_SITE_URL);
                            String dil = s.getString(TAG_DIL);

                            // Temporary HashMap for Single Data
                            HashMap<String, String> site = new HashMap<String, String>();

                            // Adding each child node to Hashmap key => value
                            site.put(TAG_SITE_ID, id);
                            site.put(TAG_SITE_URL, siteurl);
                            site.put(TAG_DIL, dil);
                            // Log.d("Siteler", siteurl);
                            // Adding site to siteList
                            siteList.add(site);
                        }

                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            });
            t.start();
            return null;
        }

        @Override
        protected void onPostExecute(Void result) {
            super.onPostExecute(result);
            // Dismiss the progress dialog
            if (pDialog.isShowing())
                pDialog.dismiss();
            /**
             * Updating parsed JSON data into ListView
             */
            ListAdapter adapter = new SimpleAdapter(getActivity(), siteList, R.layout.sitelerim_list_item,
                new String[] {TAG_SITE_URL}, new int[] {R.id.sitelerim_site_adi});
            setListAdapter(adapter);
        }
    }
}

fragment_layout_two.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:baselineAligned="false"
    android:orientation="horizontal"
    android:background="@drawable/bg"
    >

    <ListView
        android:id="@android:id/list"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:scrollbars="vertical"
        android:background="#00FF00"
        android:divider="#FFCC00"
        android:dividerHeight="10dp" />

    <TextView 
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="@color/list_item_title"
        android:text="new text"
        android:id="@android:id/empty"
        android:layout_gravity="left|center_vertical"/>

</LinearLayout>

This is my single row xml for the listview

sitelerim_list_item.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="@drawable/sitelerim_site_button" >

    <TextView 
        android:id="@+id/sitelerim_site_adi"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        />

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:layout_alignParentEnd="true"
        android:layout_alignParentRight="true"
        android:contentDescription="@string/desc_list_item_icon" />

</RelativeLayout>

These are my relevant codes. What do I need to add these codes so that I can see the list on my fragment?


Solution

  • You certainly shouldn't be creating a thread like that in your doInBackground().

    Here's how AsyncTask works:

    1. The onPreExecute() runs on the GUI thread; this means that it can update GUI elements, but it mustn't do any long-running tasks, because that would lock up the app.
    2. The doInBackground() gets run on a background thread automatically. You don't need to create a separate thread for this: that's the whole point of using this class. That means that it can take as long as it likes to run, but it must not interact with any GUI elements, because that can only be done from the GUI thread.
    3. The onPostExecute() runs on the GUI thread; this is where any results of the long doInBackground() computation can get applied to any GUI elements.

    The only remaining question is how you get the results of your doInBackground() operation passed to onPostExecute().

    You might notice that AsyncTask is a parameterised class. You've created one that takes three lots of Void, like this:

    AsyncTask<Void, Void, Void>
    

    I wouldn't worry about the first two type parameters for now, but the third is important. It specifies the result type of doInBackground(), and the parameter that gets passed to onPostExecute(). So if you change this to (for instance)

    AsyncTask<Void, Void, ArrayList<HashMap<String, String>>>
    

    then you need your return type of doInBackground() to be ArrayList<HashMap<String, String>>. You construct one of these in that method, by reading the JSON from the remote server or whatever, and then return it at the end. Now your onPostExecute() method also will take one of these as a parameter:

    protected void onPostExecute(ArrayList<HashMap<String, String>> myList) {
        //...
    }
    

    In there, you can do what you want with the list you created in doInBackground(), and apply it as you wish to GUI elements.