2017-08-12 54 views
1

我想使用AsyncTask在后台检索照片。我以base64编码形式获取照片为字符串。但是,我有“应用程序可能在其主线程上做了太多工作”错误消息。从json获取图像获取“应用程序可能在其主线程上做了太多工作”错误

我的活动:

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

放哪儿你初始化'设备'ArrayList? –

+0

是的,我从之前的活动中得到它 – Madina

+0

您是否尝试过在线程中使用新的Runnable()?像'Thread t1 = new Thread(new Runnable(){ public void run() { // code goes here。 }}); t1.start();' –

回答

1

我无法确定没有可运行版本的代码,但我猜想 行onPostExecute()导致“主线程工作太多”问题。在onPostExecute()中发生的任何事情都发生在主线程上,因此您希望尽可能保持该方法尽可能轻。正如SRB建议的那样,您可以通过让doInBackground返回位图来避免这种情况,而不是需要将其转换回位图的字符串。需要注意的是改变返回类型,则需要在两个地方改变StringBitmap

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类的doInBackground方法将被执行。 doInBackground方法总是在后台线程上运行(请参阅“4步”部分here),因此没有必要在initImages()方法中创建新线程。

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

  3. 有图像加载库像PicassoGlide将为您做背景图像提取。我不知道你的网络API是什么样子,但如果你能使用先前存在的库可以使简单快速地与像占位符,缓存大小调整的问题处理等

+0

我没有帮助。我改变了我的代码。完整的应用程序在https://git.4u.uz/Madina-S/MyApplication – Madina

+0

而不是链接到你的整个应用程序,你可以创建一个简单的例子来重现问题,然后发布相关的代码位?有关更多详细信息,请参见[this](https://stackoverflow.com/help/mcve)。 – Michiyo

相关问题