2017-08-12 63 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

相關問題