2012-02-19 36 views
5

我把JSON對象從我的服務器上的PHP腳本生成,然後使用延遲加載的圖像解析爲列表視圖。問題在於json的加載速度會相對較快,或者會根據服務器上的響應而暫停一兩秒鐘,這可能令人沮喪。當我第一次打開應用程序的竅門是espcially煩人,因爲它會在一個黑色屏幕,直到對象已經加載掛,然後當我更新的應用程序具有相同的,但至少認爲已經加載列表。這裏是我的代碼來獲取JSON:設置異步任務加載JSON轉換成一個ListView

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);   
} 

適配器代碼:

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; 
    } 

} 

我怎麼能執行一個異步任務,以顯示進度對話框,而正在生成並下載了JSON對象?我試過使用線程和異步任務,但我無法弄清楚如何將代碼拆分成適當的部分。

+0

你應該總是創建一個單獨的線程來處理JSON取。這樣你的應用程序就不會掛起。不完全是你想要的,但是當你的線程獲取JSON時,你可以顯示一個'Loading ...'文本作爲彈出窗口,並在獲取JSON後自動解除。 – Urban 2012-02-19 22:09:46

+0

任何想法如何我可以使我上面列出的Json函數的線程? – Nick 2012-02-19 22:10:53

+0

這可能有所幫助:http://stackoverflow.com/a/3027900/595947 – Urban 2012-02-19 22:20:19

回答

17

的onPreExecute,的AsyncTask的onPostExecute將在UI線程中運行,該doInBackground將在另一個線程中運行,因此下面的代碼應該只是罰款你

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; 
    .... 
} 
2

您在找什麼:progressDialog in AsyncTask查看大多數贊成票的答案,應該給你一個關於如何與進度對話框進行異步的想法。另外,如果您完全不熟悉AsyncTask,請查看this

0

這是一個簡單的線程,當您獲取數據時將顯示不確定的ProgressDialog,然後在線程完成執行後退出。

... 
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(); 
... 
0

一旦你的asynctask運行成功,它可能是值得的,同時改變你的listview來使用fragment代替。這樣做,如果列表的適配器當前爲空,您將獲得一個不錯的旋轉進度輪。 這種情況發生時,你使用默認的列表視圖項,或包含在您的自定義佈局list_content佈局。

最好的方法是創建你的活動,啓動你的asyncTask,並在任務的onpostexecute方法中設置listfragment的適配器。這樣,您將在下載數據時獲得一個不錯的加載屏幕。

參見: http://developer.android.com/reference/android/app/ListFragment.html#setListShown(boolean

0

如果要使用線程,那麼這是簡單的解決方案

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(); 
       } 
    } 
} 

注意內部thread.That從不更新UI就是爲什麼我有一個採取處理class.After執行的線程它會到處理器,然後將所有值列出適配器並關閉進度對話框