5

I take json object generate from a PHP script on my server and then parse it into a listview using a lazy load for the images. The problem is that the json will load relatively fast or it will hang for second or two depending on the response on the server, which can be frustrating. When I first open the app the hang is espcially annoying because it will hang at a black screen until the object has been loaded and then when I update the list in app it has the same but at least the view has been loaded. Here is my code to get the json:

public void getJson(String selection, String url) {
    JSONObject json = null;
    String formatedcat = selection.toLowerCase();
    ArrayList<HashMap<String, String>> mylist = new ArrayList<HashMap<String, String>>();
    json = JSONfunctions
            .getJSONfromURL(url);
    try {
        //the array title that you parse
        JSONArray category = json.getJSONArray(formatedcat);
        for (int i = 0; i < category.length(); i++) {               
            HashMap<String, String> map = new HashMap<String, String>();
            JSONObject c = category.getJSONObject(i);
            map.put("id", String.valueOf(i));
            map.put("name",
                    c.getString("title"));
            //map.put("text",c.getString("title"));
            map.put("ts",c.getString("run_date") );
            map.put("image","http:"+c.getString("url"));
            mylist.add(map);
        }
    } catch (JSONException e) {

    }
    ListAdapter adapter = new JsonAdapter(this, mylist, R.layout.list,
            new String[] { "name", "text", "ts"}, new int[] { R.id.item_title,
                    R.id.item_subtitle, R.id.timestamp});
    setListAdapter(adapter);        
}

Adapter Code:

public class JsonAdapter extends SimpleAdapter {

    public ImageManager imageManager;
    public ListActivity context;
    public ArrayList<HashMap<String,String>> list;
    public String[] fieldNames;
    public int[] fieldTargetIds;

    public JsonAdapter(ListActivity c, 
            ArrayList<HashMap<String, String>> mylist,
            int textViewResourceId,
            String[] fieldNames,
            int[] fieldTargetIds) {
        super(c, mylist, textViewResourceId, fieldNames, fieldTargetIds );
        this.context = c;
        this.list = mylist;
        this.fieldNames = fieldNames;
        this.fieldTargetIds = fieldTargetIds;
        this.imageManager = new ImageManager(context.getApplicationContext());
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        View row = convertView;
        if (row == null) {
            LayoutInflater vi = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            row = vi.inflate(R.layout.list, null);
        }
        //super.getView(position, convertView, parent);
        ImageView imgView = (ImageView) row.findViewById(R.id.doodlepic);

        try {
            String url = list.get(position).get("image");
            imgView.setTag(url);
            imageManager.displayImage(url, context, imgView);
        } catch (Exception e) {

        }

        for (int i=0; i<fieldNames.length; i++) {
            TextView tv = (TextView) row.findViewById(fieldTargetIds[i]);
            tv.setText(list.get(position).get(fieldNames[i]));              
        }


        return row;
    }

}

How could I implement an async task to show a progress dialog while the json object is being generated and downloaded? I've tried using threads and Async task but I can't quite figure out how to break apart my code into the appropriate parts.

Nick
  • 9,285
  • 33
  • 104
  • 147
  • You should always create a separate thread to handle the JSON fetching. This way your app wont hang. Not exactly what you want, but you can show a 'Loading...' Text as a popup while your thread fetches the JSON, and dismiss it automatically once its been fetched. – Urban Feb 19 '12 at 22:09
  • Any idea how I can make a thread for the Json function I listed above? – Nick Feb 19 '12 at 22:10
  • this might help: http://stackoverflow.com/a/3027900/595947 – Urban Feb 19 '12 at 22:20

5 Answers5

17

The onPreExecute , onPostExecute of AsyncTask will run in the UI thread, the doInBackground will run in another thread, so below code should just fine for you

public class YourActivity extends Activiy{
   public void getJson(String selection, String url) { 
           new LoadJsonTask().execute( selection, url);

   }
   private class LoadJsonTask extends AsyncTask<String, Void, ArrayList<HashMap<String, String>> > {
       ProgressDialog dialog ;
       protected void onPreExecute (){
            dialog = ProgressDialog.show(YourActivity.this ,"title","message");

       }
       protected ArrayList<HashMap<String, String>> doInBackground (String... params){
           return doGetJson(params[0],params[1]);
       }
       protected void onPostExecute(ArrayList<HashMap<String, String>> mylist){

            ListAdapter adapter = new JsonAdapter(YourActivity.this, mylist, R.layout.list,
              new String[] { "name", "text", "ts"}, new int[] { R.id.item_title,
                R.id.item_subtitle, R.id.timestamp});
            setListAdapter(adapter);
            dialog.dismiss();
       }
    }

 public ArrayList<HashMap<String, String>> doGetJson(String selection, String url) {
     JSONObject json = null;
     String formatedcat = selection.toLowerCase();
     ArrayList<HashMap<String, String>> mylist = new ArrayList<HashMap<String, String>>();
     json = JSONfunctions
        .getJSONfromURL(url);
     try {
    //the array title that you parse
    JSONArray category = json.getJSONArray(formatedcat);
    for (int i = 0; i < category.length(); i++) {               
        HashMap<String, String> map = new HashMap<String, String>();
        JSONObject c = category.getJSONObject(i);
        map.put("id", String.valueOf(i));
        map.put("name",
                c.getString("title"));
        //map.put("text",c.getString("title"));
        map.put("ts",c.getString("run_date") );
        map.put("image","http:"+c.getString("url"));
        mylist.add(map);
    }
} catch (JSONException e) {

}
   return mylist;
  ....   
}
Jammy Lee
  • 1,496
  • 1
  • 14
  • 32
2

Here's what you're looking for: progressDialog in AsyncTask check out the answer with most upvotes, should give you an idea on how to do async with progress dialog. Also, if you're totally unfamiliar with AsyncTask, check out this

Community
  • 1
  • 1
Ivan Bartsov
  • 19,664
  • 7
  • 61
  • 59
0

Here is a simple thread that will display an indeterminate ProgressDialog while you fetch your data and then dismiss itself once the thread is finished executing.

...
final ProgressDialog pd = ProgessDialog.show(this, "some title", "some message", true);
Thread t = new Thread(new Runnable(){
    @Override
    public void run(){
       //your code
       ....

       pd.dimiss();
    }
 });
 t.start();
 ...
pandavid87
  • 151
  • 2
0

Once you have your asynctask running successfully, it might be worth your while to change your listview to use fragments instead. In doing so, you get a nice spinning progress wheel if the list's adapter is currently empty. This happens when you use the default list view item, or including the list_content layout in your custom layout.

Best way to do this is create your activty, start your asynctask and in the task's onpostexecute method, set the listfragment's adapter up. This way you'll get a nice loading screen while your data is downloaded.

See: http://developer.android.com/reference/android/app/ListFragment.html#setListShown(boolean)

luuts
  • 652
  • 4
  • 12
0

If you want to use thread then this is simple solution

    public class ActivityClass extends Activity implements Runnable, OnItemClickListener {
    ProgressDialog pd;
    ListView list;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        list=(ListView) findViewById(R.id.listview);
        list.setOnItemClickListener(this);
        pd=new ProgressDialog(this);
        pd.setTitle("Please wait");
        pd.setMessage("Loading....");
        pd.setCancelable(false);pd.show();
        Thread th=new Thread(this);
        th.start();
    }

       AlertDialog dialog1;
       private ArrayList<String> titleVal=new ArrayList<String>();
       private ArrayList<String> pubDateVal=new ArrayList<String>();
       private ArrayList<String> linkVal=new ArrayList<String>();

        @Override
    public void run() {
        GetTheFout();
    }
    /**
     * Update If Needed
     */
    ArrayList<Long> count;
        AdapterClass adb;
    public void GetTheFout(){
        try{
        Do json parsing here and store values in arraylist,
        }
        hanlder.sendEmptyMessage(sendMsg);
    }
    private Handler hanlder=new Handler(){

        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
                adb=new AdapterClass(BBNewsMain.this,titleVal,pubDateVal);
            list.setAdapter(adb);
        }

    };
//  BroadCast broad;
    @Override
    public void onItemClick(AdapterView<?> arg0, View arg1, int pos, long arg3) {
               try{
           ///Handle click event here
               }catch(ArrayIndexOutOfBoundsException e){
                   e.getMessage();
               }
    }
}

Note Never Update UI inside thread.That's why i have taken one handler class.After executing thread it will come to handler then set all value to list adapter and dismiss Progress Dialog

Nick
  • 9,285
  • 33
  • 104
  • 147
Tofeeq Ahmad
  • 11,935
  • 4
  • 61
  • 87