Настройка асинхронной задачи для загрузки Json в просмотр списка - PullRequest
5 голосов
/ 20 февраля 2012

Я беру json object generate из PHP-скрипта на моем сервере, а затем анализирую его в виде списка, используя ленивую загрузку изображений.Проблема в том, что json будет загружаться относительно быстро или зависнет на секунду или две в зависимости от ответа на сервере, что может быть неприятно.Когда я впервые открываю приложение, зависание особенно раздражает, потому что оно будет висеть на черном экране, пока объект не будет загружен, а затем, когда я обновляю список в приложении, он имеет то же самое, но по крайней мере представление было загружено.Вот мой код для получения 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);        
}

Код адаптера:

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 искачал?Я пытался использовать потоки и асинхронную задачу, но не могу понять, как разбить мой код на соответствующие части.

Ответы [ 5 ]

17 голосов
/ 27 февраля 2012

OnPreExecute, onPostExecute из AsyncTask будет выполняться в потоке пользовательского интерфейса, 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 голосов
/ 20 февраля 2012

Вот то, что вы ищете: progressDialog в AsyncTask проверьте ответ с большинством голосов, должны дать вам представление о том, как сделать асинхронность с диалогом прогресса.Кроме того, если вы совершенно незнакомы с AsyncTask, проверьте это

0 голосов
/ 29 февраля 2012

Если вы хотите использовать поток, то это простое решение

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

Примечание Никогда не обновлять пользовательский интерфейс внутри потока. Поэтому я выбрал один класс обработчика. После выполнения потока он перейдет к обработчику, затем установит все значения в список адаптеров и закроет диалог прогресса

0 голосов
/ 20 февраля 2012

Как только вы успешно запустите асинхронную задачу, возможно, стоит поменять вид списка, чтобы использовать вместо него фрагменты.При этом вы получите отличное вращающееся колесо прогресса, если адаптер списка в данный момент пуст.Это происходит при использовании элемента представления списка по умолчанию или при включении макета list_content в пользовательский макет.

Лучший способ сделать это - создать актив, запустить асинхронную задачу и в методе задачи onpostexecute установить адаптер listfragment.Таким образом, вы получите хороший экран загрузки, пока ваши данные загружаются.

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

0 голосов
/ 20 февраля 2012

Вот простой поток, который будет отображать неопределенный 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();
 ...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...