从Async Task上的URL获取数据时,主线程冻结

时间:2013-01-29 10:48:52

标签: android android-asynctask json

我使用AsycTask从URL获取JSON,解析它并将数据显示在listView上。我还单击刷新按钮再次从URL获取JSON以进行一些更新。当我点击刷新按钮时,会发生以下情况; 1)adapter.clear():清除listView的适配器以填充新数据。 2)从url获取JSON,解析并将新获取的数据显示到listView上。 3)同时在获取数据时,我会显示一个进度对话框。

但是当我点击刷新按钮时,主UI线程在执行AsynTask期间冻结。我的意思是刷新按钮看起来按下,直到AsynTask完成作业,如下所示。 enter image description here

这是我的代码:

public class AndroidJSONParsingActivity extends SherlockActivity {

    // JSON Node names
    ArrayList<HashMap<String, String>> placeList = new ArrayList<HashMap<String, String>>();
    private static final String TAG_PLACES = "places";
    private static final String TAG_PLACE_NAME = "name";
    private static final String TAG_PLACE_CATEGORY = "category";
    private static final String TAG_PLACE_DISTANCE = "distance";
    private static final String TAG_TRAVEL_TIME = "travel_time";
    ListAdapter adapter;
    public static Context con;
    JSONArray places = null;
    ListView list;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        con = this;
        list = (ListView) findViewById(R.id.listView1);
        parseJSON();

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {

        MenuInflater inflater = getSupportMenuInflater();
        inflater.inflate(R.menu.activity_main, menu);

        MenuItem menu_item1 = menu.findItem(R.id.menu_item1);

        menu_item1.setOnMenuItemClickListener(new OnMenuItemClickListener() {

            @Override
            public boolean onMenuItemClick(MenuItem item) {
                Toast.makeText(getApplicationContext(), "refresh",
                        Toast.LENGTH_LONG).show();
                placeList.clear();
                parseJSON();
                return false;
            }
        });

        return true;

    }

    public void parseJSON() {
        try {
            placeList = new JSONParsingTask().execute().get();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (ExecutionException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        adapter = new SimpleAdapter(this, placeList, R.layout.list_item,
                new String[] { TAG_PLACE_NAME, TAG_PLACE_CATEGORY,
                        TAG_PLACE_DISTANCE, TAG_TRAVEL_TIME }, new int[] {
                        R.id.name, R.id.category, R.id.distance,
                        R.id.travel_time });

        list.setAdapter(adapter);

        list.setOnItemClickListener(new OnItemClickListener() {

            @Override
            public void onItemClick(AdapterView<?> parent, View view,
                    int position, long id) {
                String name = ((TextView) view.findViewById(R.id.name))
                        .getText().toString();
                String category = ((TextView) view.findViewById(R.id.category))
                        .getText().toString();
                String distance = ((TextView) view.findViewById(R.id.distance))
                        .getText().toString();
                String travel_time = ((TextView) view
                        .findViewById(R.id.travel_time)).getText().toString();

                Intent in = new Intent(getApplicationContext(),
                        SingleMenuItemActivity.class);
                in.putExtra(TAG_PLACE_NAME, name);
                in.putExtra(TAG_PLACE_CATEGORY, category);
                in.putExtra(TAG_PLACE_DISTANCE, distance);
                in.putExtra(TAG_TRAVEL_TIME, travel_time);
                startActivity(in);

            }
        });

    }

}

class JSONParsingTask extends
        AsyncTask<Void, Void, ArrayList<HashMap<String, String>>> {
    public Boolean flag = false;
    private static String url = "http://some - url";

    // JSON Node names

    private static final String TAG_PLACES = "places";
    private static final String TAG_PLACE_NAME = "name";
    private static final String TAG_PLACE_CATEGORY = "category";
    private static final String TAG_PLACE_DISTANCE = "distance";
    private static final String TAG_TRAVEL_TIME = "travel_time";
    ListAdapter adapter;
    JSONParser jParser;
    ListView list;
    static ArrayList<HashMap<String, String>> placeList = new ArrayList<HashMap<String, String>>();
    JSONArray places = null;

    ProgressDialog JSONParsingDialog = new ProgressDialog(
            AndroidJSONParsingActivity.con);

    @Override
    protected void onPreExecute() {
        JSONParsingDialog.setMessage("Preparing data...");
        JSONParsingDialog.setCanceledOnTouchOutside(false);
        JSONParsingDialog.setCancelable(false);
        JSONParsingDialog.show();
    }

    @Override
    protected ArrayList<HashMap<String, String>> doInBackground(Void... params) {
        JSONParser jParser = new JSONParser();

        final JSONObject json = jParser.getJSONFromUrl(url);

        try {
            places = json.getJSONArray(TAG_PLACES);

            for (int i = 0; i < places.length(); i++) {
                JSONObject c = places.getJSONObject(i);

                String name = c.getString(TAG_PLACE_NAME);
                String category = c.getString(TAG_PLACE_CATEGORY);
                String distance = c.getString(TAG_PLACE_DISTANCE);
                String travel_time = c.getString(TAG_TRAVEL_TIME);

                HashMap<String, String> map = new HashMap<String, String>();

                map.put(TAG_PLACE_NAME, name);
                map.put(TAG_PLACE_CATEGORY, category);
                map.put(TAG_PLACE_DISTANCE, distance);
                map.put(TAG_TRAVEL_TIME, travel_time);

                placeList.add(map);
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }
        return placeList;
    }

    @Override
    protected void onPostExecute(ArrayList<HashMap<String, String>> result) {
        // TODO Auto-generated method stub
        super.onPostExecute(result);
        JSONParsingDialog.dismiss();
    }

}

我需要的是,当我点击刷新按钮时,它应该是平滑的,并且在AsynTask完成之前不应该冻结。知道我该怎么办?

2 个答案:

答案 0 :(得分:4)

使用

new JSONParsingTask().execute(); 

.get()会阻止调用者线程。

更多信息:Looking for good example of using get() with an AsyncTask in android

答案 1 :(得分:2)

试试这样:

public class AndroidJSONParsingActivity extends SherlockActivity {

// JSON Node names
ArrayList<HashMap<String, String>> placeList = new ArrayList<HashMap<String, String>>();
private static final String TAG_PLACES = "places";
private static final String TAG_PLACE_NAME = "name";
private static final String TAG_PLACE_CATEGORY = "category";
private static final String TAG_PLACE_DISTANCE = "distance";
private static final String TAG_TRAVEL_TIME = "travel_time";
ListAdapter adapter;
public static Context con;
JSONArray places = null;
ListView list;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    con = this;
    list = (ListView) findViewById(R.id.listView1);
    fetchJSON();

}

@Override
public boolean onCreateOptionsMenu(Menu menu) {

    MenuInflater inflater = getSupportMenuInflater();
    inflater.inflate(R.menu.activity_main, menu);

    MenuItem menu_item1 = menu.findItem(R.id.menu_item1);

    menu_item1.setOnMenuItemClickListener(new OnMenuItemClickListener() {

        @Override
        public boolean onMenuItemClick(MenuItem item) {
            Toast.makeText(getApplicationContext(), "refresh",
                    Toast.LENGTH_LONG).show();
            placeList.clear();
            parseJSON();
            return false;
        }
    });

    return true;

}

public void fecthJson(){
    new JSONParsingTask().execute();
}

public void parseJSON(ArrayList<Hashmap<String, String>> dataList) {

    adapter = new SimpleAdapter(this, dataList, R.layout.list_item,
            new String[] { TAG_PLACE_NAME, TAG_PLACE_CATEGORY,
                    TAG_PLACE_DISTANCE, TAG_TRAVEL_TIME }, new int[] {
                    R.id.name, R.id.category, R.id.distance,
                    R.id.travel_time });

    list.setAdapter(adapter);

    list.setOnItemClickListener(new OnItemClickListener() {

        @Override
        public void onItemClick(AdapterView<?> parent, View view,
                int position, long id) {
            String name = ((TextView) view.findViewById(R.id.name))
                    .getText().toString();
            String category = ((TextView) view.findViewById(R.id.category))
                    .getText().toString();
            String distance = ((TextView) view.findViewById(R.id.distance))
                    .getText().toString();
            String travel_time = ((TextView) view
                    .findViewById(R.id.travel_time)).getText().toString();

            Intent in = new Intent(getApplicationContext(),
                    SingleMenuItemActivity.class);
            in.putExtra(TAG_PLACE_NAME, name);
            in.putExtra(TAG_PLACE_CATEGORY, category);
            in.putExtra(TAG_PLACE_DISTANCE, distance);
            in.putExtra(TAG_TRAVEL_TIME, travel_time);
            startActivity(in);

        }
    });

}

}

class JSONParsingTask extends
    AsyncTask<Void, Void, ArrayList<HashMap<String, String>>> {
public Boolean flag = false;
private static String url = "http://some - url";

// JSON Node names

private static final String TAG_PLACES = "places";
private static final String TAG_PLACE_NAME = "name";
private static final String TAG_PLACE_CATEGORY = "category";
private static final String TAG_PLACE_DISTANCE = "distance";
private static final String TAG_TRAVEL_TIME = "travel_time";
ListAdapter adapter;
JSONParser jParser;
ListView list;
static ArrayList<HashMap<String, String>> placeList = new ArrayList<HashMap<String, String>>();
JSONArray places = null;

ProgressDialog JSONParsingDialog = new ProgressDialog(
        AndroidJSONParsingActivity.con);

@Override
protected void onPreExecute() {
    JSONParsingDialog.setMessage("Preparing data...");
    JSONParsingDialog.setCanceledOnTouchOutside(false);
    JSONParsingDialog.setCancelable(false);
    JSONParsingDialog.show();
}

@Override
protected ArrayList<HashMap<String, String>> doInBackground(Void... params) {
    JSONParser jParser = new JSONParser();

    final JSONObject json = jParser.getJSONFromUrl(url);

    try {
        places = json.getJSONArray(TAG_PLACES);

        for (int i = 0; i < places.length(); i++) {
            JSONObject c = places.getJSONObject(i);

            String name = c.getString(TAG_PLACE_NAME);
            String category = c.getString(TAG_PLACE_CATEGORY);
            String distance = c.getString(TAG_PLACE_DISTANCE);
            String travel_time = c.getString(TAG_TRAVEL_TIME);

            HashMap<String, String> map = new HashMap<String, String>();

            map.put(TAG_PLACE_NAME, name);
            map.put(TAG_PLACE_CATEGORY, category);
            map.put(TAG_PLACE_DISTANCE, distance);
            map.put(TAG_TRAVEL_TIME, travel_time);

            placeList.add(map);
        }
    } catch (JSONException e) {
        e.printStackTrace();
    }
    return placeList;
}

@Override
protected void onPostExecute(ArrayList<HashMap<String, String>> result) {
    // TODO Auto-generated method stub
    super.onPostExecute(result);
    JSONParsingDialog.dismiss();
    placeList = result;
    parseJson(result);
}

}