2012-02-19 30 views
5

Tôi lấy đối tượng json sinh ra từ một tập lệnh PHP trên máy chủ của tôi và sau đó phân tích nó thành một listview bằng cách sử dụng một tải lười cho các hình ảnh. Vấn đề là các json sẽ tải tương đối nhanh hoặc nó sẽ treo cho thứ hai hoặc hai tùy thuộc vào phản ứng trên máy chủ, mà có thể được bực bội. Khi tôi lần đầu tiên mở ứng dụng, hang sẽ khó chịu bởi vì nó sẽ treo ở màn hình màu đen cho đến khi đối tượng được tải và sau đó khi tôi cập nhật danh sách trong ứng dụng, nó có cùng nhưng ít nhất chế độ xem đã được tải. Đây là mã của tôi để có được những json:Thiết lập tác vụ không đồng bộ để tải Json vào một 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);   
} 

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

} 

Làm thế nào tôi có thể thực hiện một nhiệm vụ async để hiển thị một hộp thoại tiến trình trong khi đối tượng json đang được tạo và tải? Tôi đã thử sử dụng các chủ đề và tác vụ Async nhưng tôi không thể tìm ra cách để tách mã của tôi thành các phần thích hợp.

+0

Bạn nên luôn tạo một chuỗi riêng biệt để xử lý việc tìm nạp JSON . Bằng cách này, ứng dụng của bạn sẽ không bị treo. Không chính xác những gì bạn muốn, nhưng bạn có thể hiển thị văn bản 'Đang tải ...' dưới dạng cửa sổ bật lên trong khi chuỗi của bạn tìm nạp JSON và loại bỏ nó tự động sau khi được tìm nạp. – Urban

+0

Bất kỳ ý tưởng làm thế nào tôi có thể làm cho một sợi cho các chức năng Json tôi liệt kê ở trên? – Nick

+0

điều này có thể giúp: http://stackoverflow.com/a/3027900/595947 – Urban

Trả lời

17

Các onPreExecute, onPostExecute của AsyncTask sẽ chạy trong thread UI, các doInBackground sẽ chạy trong thread khác, vì vậy mã dưới đây nên chỉ tốt cho bạn

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

Dưới đây là những gì bạn đang tìm kiếm: progressDialog in AsyncTask kiểm tra câu trả lời với hầu hết các phiếu bầu, nên cung cấp cho bạn ý tưởng về cách thực hiện async với hộp thoại tiến trình. Ngoài ra, nếu bạn hoàn toàn không quen thuộc với AsyncTask, hãy xem this

0

Đây là một chuỗi đơn giản sẽ hiển thị ProgressDialog không xác định trong khi bạn tìm nạp dữ liệu của mình và sau đó loại bỏ chính nó sau khi chạy xong.

... 
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

Khi bạn có asynctask đang chạy thành công, có thể đáng để bạn thay đổi chế độ xem danh sách để sử dụng các đoạn thay thế. Khi làm như vậy, bạn sẽ có được một bánh xe tiến bộ quay đẹp nếu bộ điều hợp danh sách hiện đang trống. Điều này xảy ra khi bạn sử dụng mục xem danh sách mặc định hoặc bao gồm bố cục list_content trong bố cục tùy chỉnh của bạn.

Cách tốt nhất để thực hiện việc này là tạo hoạt động, khởi động asynctask của bạn và trong phương thức onpostexecute của công việc, đặt bộ điều hợp danh sách lên. Bằng cách này, bạn sẽ nhận được một màn hình tải tốt đẹp trong khi dữ liệu của bạn được tải xuống.

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

0

Nếu bạn muốn sử dụng thread thì đây là giải pháp đơn giản

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

Lưu ý Không bao giờ cập nhật giao diện người dùng bên trong thread.Đó là lý do tại sao tôi đã thực hiện một lớp trình xử lý. Sau khi thực thi luồng, nó sẽ đến trình xử lý rồi đặt tất cả giá trị thành bộ điều hợp danh sách và bỏ qua Hộp thoại tiến trình

Các vấn đề liên quan