2012-02-19 61 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执行的线程它会到处理器,然后将所有值列出适配器并关闭进度对话框