代码之家  ›  专栏  ›  技术社区  ›  Madina

在从json检索图像时,get出现“应用程序可能在其主线程上做了太多工作”错误

  •  1
  • Madina  · 技术社区  · 8 年前

    我想使用AsyncTask在后台检索照片。我以base64编码的形式获取照片作为字符串。然而,我收到了“应用程序可能在其主线程上做了太多工作”的错误消息。

    public class MainActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener, ItemClickHandler{
    
        private RecyclerView recyclerView;
        private RecyclerViewAdapter adapter;
        private LayoutManager layoutManager;
    
        private ArrayList<Device> devices;
    
    @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_action_bar);
    
            recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
            recyclerView.setHasFixedSize(true);
    
            layoutManager = new LinearLayoutManager(this);
            recyclerView.setLayoutManager(layoutManager);
            adapter = new RecyclerViewAdapter(devices, this);
            recyclerView.setAdapter(adapter);
    
            initImages();
        }
    
        private void initImages() {
            Thread thread = new Thread() {
                @Override
                public void run() {
                    for(int i = 0; i < devices.size(); i++){
                        final int pos = i;
                        GetImageJSON getImage = new GetImageJSON(MainActivity.this){
                            @Override
                            protected void onPostExecute(final String result) {
                                Log.d(TAG, result);
    
                                if(pos <= recyclerView.getLayoutManager().getChildCount()){
                                    adapter.updateItem(ImageManager.convertToBitmap(result), pos);
                                }
                            }
                        };
                        getImage.execute(ConnectionConfig.getUserItemImage(devices.get(i).getId()));
                    }
                }
            };
            thread.start();
        }
    }

    GetImageJSON类:

    public class GetDataJSON extends AsyncTask<String, Void, String> {
    
        private static String charset = "UTF-8";
    
        @Override
        protected String doInBackground(String... args) { 
            String result = parseJSONString(args[0]);
            if(!result.isEmpty()){
                try{
                    JSONObject json = new JSONObject(result);
                    JSONObject jsonObject = json.getJSONObject(ConnectionConfig.TAG_RESULT);
                    String base64String = jsonObject.getString("image");
                    Log.d(TAG, base64String);
                    Bitmap bitmap = ImageManager.convertToBitmap(base64String);
                    bitmap = ImageManager.scaleDownBitmap(bitmap, context);
                    Log.d(TAG, "got result: " + result);
                    return ImageManager.convertBitMapToString(bitmap);
                }catch (JSONException e){
                    e.printStackTrace();
                }
            }
    
            return result;
        }
    
        public static String parseJSONString(String... args){
            String result = "";
            InputStream inputStream = null;
    
            Log.d(TAG, args[0]);
            try {
                URL url = new URL(args[0]);
                HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
    
                conn.setDoOutput(false);
                conn.setRequestMethod("GET");
                conn.setRequestProperty("Accept-Charset", charset);
                conn.setConnectTimeout(15000);
                conn.connect();
    
                try {
                    InputStream in = new BufferedInputStream(conn.getInputStream());
                    BufferedReader reader = new BufferedReader(new InputStreamReader(in));
                    String line;
                    while ((line = reader.readLine()) != null) {
                        result += line;
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
    
                conn.disconnect();
            } catch (Exception e) {
                Log.d(TAG, "Exception", e);
            } finally {
                try{
                    if(inputStream != null)
                        inputStream.close();
                }catch(Exception e){
                    Log.d(TAG, e.getMessage());
                }
            }
    
            return result;
        }
    }

    我找不到任何解决办法。请随便推荐一个。如何优化检索数据的过程。

    1 回复  |  直到 8 年前
        1
  •  1
  •   Michiyo    8 年前

    如果没有你的代码的可运行版本,我无法确定,但我猜这句话 ImageManager.convertToBitmap(result) 在里面 onPostExecute() 导致“主线程上的工作过多”问题。任何发生在 发生在主线程上,因此您希望使该方法尽可能轻。正如SRB所建议的,您可以通过 doInBackground 返回位图,而不是需要转换回位图的字符串。注意,要更改返回类型,您需要更改 String Bitmap 在两个地方:

    public class GetDataJSON extends AsyncTask<String, Void, Bitmap> {
    
        @Override
        protected Bitmap doInBackground(String... args) {
            // TODO return the bitmap
        }
    
        //...the rest of your code
    
    }
    

    另一方面,您的代码似乎还有改进的空间。这些事情与你的问题没有直接关系,但最好能理解。

    1. 当你打电话的时候 getImage.execute() , 方法 GetDataJSON 类将被执行。这个 Doin背景 here initImages() 方法

    2. 使用recyclerview的好处之一是,当recyclerview出现在屏幕上时,您不需要加载所有内容。如果有屏幕外的视图,则可以在用户向其滚动时创建这些视图。通过在创建活动时检索所有图像,您将失去这一优势。

    3. 有图像加载库,如 Picasso Glide