【问题标题】:Two AsyncTasks block each others两个 AsyncTask 互相阻塞
【发布时间】:2017-05-15 19:32:21
【问题描述】:

我创建了一个android 应用程序,它从google place api 获取一些数据。它在AsyncTask 中返回一个Json object。然后我将每条记录放入对象的list 中,并在该列表中执行一些需要来自DB 的数据的操作。因为它是一个简单的应用程序,所以我使用JDBC 连接到database。当我对上面的列表进行一些操作时,我的UI 会长时间阻塞。方法如下:

private void generateMap(LatLng latLng, String distance) {
        List<WashLocation> list = new ArrayList<>();

        MyAsyncTask myAsyncTask = new MyAsyncTask();

        try {
            JSONObject jsonObject = myAsyncTask.execute(latitude, longitude, radius).get();
            String lat;
            String lng;
            String name = "";
            String city = "";
            String placeId = "";
            if (jsonObject != null) {
                if (jsonObject.has("results")) {
                    JSONArray jsonArray = jsonObject.getJSONArray("results");
                    for (int n = 0; n < jsonArray.length(); n++) {
                        JSONObject jsonObject1 = jsonArray.getJSONObject(n);
                        lat = jsonObject1.getJSONObject("geometry").getJSONObject("location").get("lat").toString();
                        lng = jsonObject1.getJSONObject("geometry").getJSONObject("location").get("lng").toString();

                        JSONObject oName = jsonArray.getJSONObject(n);
                        if (oName.has("name")) {
                            name = oName.getString("name");
                        }

                        JSONObject oVicinity = jsonArray.getJSONObject(n);
                        if (oVicinity.has("vicinity")) {
                            city = oVicinity.getString("vicinity");
                        }
                        JSONObject oPlaceId = jsonArray.getJSONObject(n);
                        if (oPlaceId.has("place_id")) {
                            placeId = oPlaceId.getString("place_id");
                        }
                        WashLocation w = new WashLocation(name, lat, lng, 0, getCity(city), null, placeId);
                        list.add(w);
                    }
                }
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        } catch (JSONException e) {
            e.printStackTrace();
        }
       for(WashLocation washLocation: list) {
       try {
           WashLocation washLocation1 = new CheckPlaceID(washLocation).execute().get();
           washLocations.add(washLocation1);
       } catch (InterruptedException e) {
           e.printStackTrace();
       } catch (ExecutionException e) {
           e.printStackTrace();
       }
   }
    }

内部类:

private class CheckPlaceID extends AsyncTask<Void, Void, WashLocation> {
        private WashLocation washLocation;
        String placeId;

        public CheckPlaceID(WashLocation washLocation) {
            this.washLocation = washLocation;
        }

        @Override
        protected void onPreExecute() {
            super.onPreExecute();

        }

        @Override
        protected void onPostExecute(WashLocation washLocation) {
            super.onPostExecute(washLocation);
        }

        @Override
        protected WashLocation doInBackground(Void... params) {
            DataBaseHelperRemote dataBaseHelperRemote = new DataBaseHelperRemote();
            List<WashLocationRemoteDB> allWashLocationFromRemoteDB = dataBaseHelperRemote.getAllWashLocationFromRemoteDB(); //data from DB
            WashLocationRemoteDB washLocationRemoteDBByPlaceId = dataBaseHelperRemote.getWashLocationRemoteDBByPlaceId(washLocation.getPlaceId()); //data from DB
            if(washLocation != null){
                if(washLocationRemoteDBByPlaceId != null){
                    if(allWashLocationFromRemoteDB != null){
                        for(WashLocationRemoteDB db : allWashLocationFromRemoteDB){
                            if(db.getPlaceId().equalsIgnoreCase(washLocation.getPlaceId())){
                                washLocation.setWashName("tu coś jest!");
                                break;
                            }
                        }
                    }
                }
            }
            return washLocation;
        }

我怎样才能提高该过程的速度并且不阻塞UI

【问题讨论】:

  • 我相信您的阻塞问题是由于您在异步任务上使用了.get。通常结果应该在回调中传回。我可能会将 JSON 解析部分包含在异步任务的后台部分中,并尝试将其减少为一个回调。
  • @AdamForbis 那么我怎样才能不使用.get获得结果?
  • 看@VeneetReddy链接,使用界面,我会在几个小时后下班,如果到时候你还想不通,给你一个实际的答案。

标签: android multithreading android-asynctask


【解决方案1】:

在处理异步 android 代码时,您通常使用接口回调。您希望作为对另一个线程的操作的结果来执行操作。永远不要等待 UI 线程的另一个线程,你会阻塞它。

一个接口示例:

/*So an interface like this */
public interface WashLocationInterface{
    public void onWashLocationRetrieved(WashLocation location);
}

AsyncTask:

/*Can be used like */
private class CheckPlaceID extends AsyncTask<Void, Void, WashLocation> {
        /* Not showing variables*/

        public CheckPlaceID(WashLocation washLocation, WashLocationInterface washLocationInterface) {
            this.washLocation = washLocation;
            /*We can pass in an implementation of this interface to the async task*/
            this.washLocationInterface = washLocationInterface;
        }
        /* Not showing on pre execute*/
        @Override
        protected void onPostExecute(WashLocation washLocation) {
            super.onPostExecute(washLocation);
            /* We call the method in the interface here,
            this will then be called in the implementation in the interface*/
            washLocationInterface.onWashLocationRetrieved(washLocation);
        }

        @Override
        protected WashLocation doInBackground(Void... params) {
           /* Not showing code for brevity*/
           /* long running work*/
            return washLocation;
        }
}

一个示例方法:

/* Example interface implementation, if */
public exampleMethod(){/* Could be some lifecycle method like onCreate*/
    /* This interface only needs created once*/
    WashLocationInterface washLocationInterface = new WashLocationInterface(){
        @Override
        public void onWashLocationRetrieved(WashLocation location){
            /* Maybe update ui in here, or call some method that needs to be called when 
            data is retrieved*/
        }
    }
    /* Pass the interface into the async task, which then can call the method*/
    new CheckPlaceID(/* Some existing wash location */washLocation, washLocationInterface).execute();
}

【讨论】:

  • 感谢您的帖子。我回家后会检查的。顺便提一句。昨天,如果我们谈论 AsyncTask,我做了一些解决方法,当我通过插入计算机的手机对其进行测试时,一切正常,但有一些延迟。但是,当我在今天未插入的手机上运行相同的应用程序时,应用程序无法正常工作。你知道(当然现在一般来说)这种行为的原因是什么?
  • 有趣的是,自从我上次测试以来我没有改变任何东西,现在它可以工作了......
  • @bielas 可以是任意数量的东西,我要做的第一件事就是检查我的堆栈跟踪。可能是网络速度不同,cpu 可以用来做节能功能,服务器出现故障。通常堆栈跟踪会告诉你原因。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-15
  • 2023-03-04
  • 2023-03-09
  • 1970-01-01
相关资源
最近更新 更多