2017-03-16 98 views
-5

JSON對象我正在從https://newsapi.org/v1/sourcesJSON對象太大。 OutOfMemoryException異常:無法分配字節

但它以數組形式返回69個對象和應用程序是無法分配這麼多的內存,我使用解析JSON一個ArrayList反對

我有以下錯誤:

03-16 13:19:51.985 14275-14275/com.example.user.bulletin E/AndroidRuntime: FATAL EXCEPTION: main 
Process: com.example.user.bulletin, PID: 14275 
java.lang.OutOfMemoryError: Failed to allocate a 506340012 byte allocation with 4369064 free bytes and 377MB until OOM 
at dalvik.system.VMRuntime.newNonMovableArray(Native Method) 
at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method) 
at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:620) 
at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:455) 
at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:1152) 
at android.content.res.ResourcesImpl.loadDrawableForCookie(ResourcesImpl.java:724) 
at android.content.res.ResourcesImpl.loadDrawable(ResourcesImpl.java:575) 
at android.content.res.Resources.getDrawable(Resources.java:767) 
at android.content.Context.getDrawable(Context.java:525) 
at android.support.v4.content.ContextCompatApi21.getDrawable(ContextCompatApi21.java:30) 
at android.support.v4.content.ContextCompat.getDrawable(ContextCompat.java:372) 
at android.support.v7.widget.AppCompatDrawableManager.getDrawable(AppCompatDrawableManager.java:202) 
at android.support.v7.widget.AppCompatDrawableManager.getDrawable(AppCompatDrawableManager.java:190) 
at android.support.v7.content.res.AppCompatResources.getDrawable(AppCompatResources.java:100) 
at android.support.v7.widget.AppCompatImageHelper.loadFromAttributes(AppCompatImageHelper.java:54) 
at android.support.v7.widget.AppCompatImageView.<init>(AppCompatImageView.java:66) 
at android.support.v7.widget.AppCompatImageView.<init>(AppCompatImageView.java:56) 
at android.support.v7.app.AppCompatViewInflater.createView(AppCompatViewInflater.java:106) 
at android.support.v7.app.AppCompatDelegateImplV9.createView(AppCompatDelegateImplV9.java:1021) 
at android.support.v7.app.AppCompatDelegateImplV9.onCreateView(AppCompatDelegateImplV9.java:1080) 
at android.support.v4.view.LayoutInflaterCompatHC$FactoryWrapperHC.onCreateView(LayoutInflaterCompatHC.java:47) 
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:769) 
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:727) 
at android.view.LayoutInflater.rInflate(LayoutInflater.java:858) 
at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:821) 
at android.view.LayoutInflater.rInflate(LayoutInflater.java:861) 
at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:821) 
at android.view.LayoutInflater.rInflate(LayoutInflater.java:861) 
at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:821) 
at android.view.LayoutInflater.inflate(LayoutInflater.java:518) 
at android.view.LayoutInflater.inflate(LayoutInflater.java:426) 
at com.example.user.bulletin.RecyclerHelpers.SourceAdapter.onCreateViewHolder(SourceAdapter.java:41) 
at com.example.user.bulletin.RecyclerHelpers.SourceAdapter.onCreateViewHolder(SourceAdapter.java:25) 
at android.support.v7.widget.RecyclerView$Adapter.createViewHolder(RecyclerView.java:6321) 
at android.support.v7.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:5509) 
at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5394) 
at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5390) 
at android.support.v7.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2149) 
at android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1533) 
at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1496) 
at android.support.v7.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:593) 
at android.support.v7.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:3537) 
at android.support.v7.widget.RecyclerView.onMeasure(RecyclerView.java:2979) 
at android.view.View.measure(View.java:19756) 
at android.widget.RelativeLayout.measureChildHorizontal(RelativeLayout.java:715) 
at android.widget.RelativeLayout.onMeasure(RelativeLayout.java:461) 
03-16 13:19:51.985 14275-14275/com.example.user.bulletin E/AndroidRuntime:  at android.view.View.measure(View.java:19756) 
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6124) 
at android.widget.FrameLayout.onMeasure(FrameLayout.java:185) 
at android.support.v7.widget.ContentFrameLayout.onMeasure(ContentFrameLayout.java:139) 
at android.view.View.measure(View.java:19756) 
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6124) 
at android.support.v7.widget.ActionBarOverlayLayout.onMeasure(ActionBarOverlayLayout.java:393) 
at android.view.View.measure(View.java:19756) 
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6124) 
at android.widget.FrameLayout.onMeasure(FrameLayout.java:185) 
at android.view.View.measure(View.java:19756) 
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6124) 
at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1464) 
at android.widget.LinearLayout.measureVertical(LinearLayout.java:758) 
at android.widget.LinearLayout.onMeasure(LinearLayout.java:640) 
at android.view.View.measure(View.java:19756) 
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6124) 
at android.widget.FrameLayout.onMeasure(FrameLayout.java:185) 
at com.android.internal.policy.DecorView.onMeasure(DecorView.java:687) 
at android.view.View.measure(View.java:19756) 
at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:2283) 
at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1370) 
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1619) 
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1258) 
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6348) 
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:871) 
at android.view.Choreographer.doCallbacks(Choreographer.java:683) 
at android.view.Choreographer.doFrame(Choreographer.java:619) 
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:857) 
at android.os.Handler.handleCallback(Handler.java:751) 
at android.os.Handler.dispatchMessage(Handler.java:95) 
at android.os.Looper.loop(Looper.java:154) 
at android.app.ActivityThread.main(ActivityThread.java:6123) 
at java.lang.reflect.Method.invoke(Native Method) 
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:867) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:757) 
03-16 13:19:55.608 14275-14287/com.example.user.bulletin W/art: Suspending all threads took: 27.278ms 

JSON對象是太大。

和一些佈局錯誤。我該如何解決這個問題?

SourceParser.java

package com.example.user.bulletin.JSON; 
import android.app.ProgressDialog; 
import android.content.Context; 
import android.os.AsyncTask; 
import android.support.v7.widget.LinearLayoutManager; 
import android.support.v7.widget.RecyclerView; 
import android.util.Log; 
import android.widget.Toast; 
import com.example.user.bulletin.RecyclerHelpers.SourceAdapter; 
import com.example.user.bulletin.RecyclerHelpers.SourceItem;  
import org.json.JSONArray; 
import org.json.JSONException; 
import org.json.JSONObject;  
import java.util.ArrayList; 

/** 
* Created by User on 14-03-2017. 
*/ 

public class SourceParser extends AsyncTask<Void, Void, Boolean> { 

    Context c; 
    String jsonData; 
    RecyclerView rv; 
    String TAG = "NOT bla bla"; 
    ProgressDialog pd; 
    ArrayList<SourceItem> sources; 

    //String id, name, description, url, category, langCode, contCode, smallLogoUrl, medLogoUrl, largeLogoUrl; 

    public SourceParser(Context c, String jsonData, RecyclerView rv) { 
     this.c = c; 
     this.jsonData = jsonData; 
     this.rv = rv; 
    } 

    @Override 
    protected void onPreExecute() { 
     super.onPreExecute(); 
     pd = new ProgressDialog(c); 
     pd.setTitle("Please wait..."); 
     pd.setMessage("Loading list of news sources"); 
     pd.show(); 
    } 

    @Override 
    protected void onPostExecute(Boolean isParsed) { 
     super.onPostExecute(isParsed); 
     pd.dismiss(); 
     if(isParsed){ 
      //bind 
      SourceAdapter adapter = new SourceAdapter(c, sources); 
      rv.setAdapter(adapter); 
      rv.setLayoutManager(new LinearLayoutManager(c)); 
     }else 
      Toast.makeText(c, "Unable to parse", Toast.LENGTH_LONG).show(); 
    } 

    @Override 
    protected Boolean doInBackground(Void... params) { 
     return parse(); 
    } 

    private boolean parse(){ 
     try{ 

      JSONObject object = new JSONObject(jsonData); 
      JSONArray jsonArray = object.getJSONArray("sources"); 
      JSONObject jsonObject; 
      sources = new ArrayList<>(); 
      sources.clear(); 
      Log.d(TAG, object.toString()); 

      for(int i=0; i<5; i++){ //jsonArray.length() 

       jsonObject = jsonArray.getJSONObject(i);  

       String id = jsonObject.getString("id"); 
       String name = jsonObject.getString("name"); 
       String description = jsonObject.getString("description"); 
       String url = jsonObject.getString("url"); 
       String category = jsonObject.getString("category"); 
       String langCode = jsonObject.getString("language"); 
       String contCode = jsonObject.getString("country"); 

       JSONObject urlObject = jsonObject.getJSONObject("urlsToLogos"); 
       String smallLogoUrl = urlObject.getString("small"); 
       String medLogoUrl = urlObject.getString("medium"); 
       String largeLogoUrl = urlObject.getString("large"); 

       sources.add(new SourceItem(id, name, description, url, category, langCode, contCode, smallLogoUrl, medLogoUrl, largeLogoUrl)); 

       String printThis = "\nNew Source - \nid : "+id+"\nname : "+ name+"\ndescription : "+description+"\nurl"+url+"\ncategory : "+category +"\nLangCode : "+langCode +"\ncontCode : "+ contCode+"\nsmall url : "+smallLogoUrl +"\nmed url : "+ medLogoUrl+"\nlarge url : "+largeLogoUrl; 
       Log.d(TAG, printThis); 

       } 

       return true; 
     } catch (JSONException e) { 
      e.printStackTrace(); 
      return false; 
     } 
    } 
} 
+0

也許這將幫助你http://stackoverflow.com/q/9390368/6171845 –

+0

@Kartik檢查下面的答案。 – Gattsu

+0

[Android:java.lang.OutOfMemoryError:無法分配一個23970828字節分配與2097152可用字節和2MB,直到OOM]可能重複(http://stackoverflow.com/questions/32244851/androidjava-lang-outofmemoryerror-failed- to-allocate-a-23970828-byte-allocatio) –

回答

2

您不能動態地增加堆大小,但你可以要求通過使用較多。

android:largeHeap="true"

manifest.xml中,您可以在您的清單中添加這些行,它適用於某些情況。

<application 
    android:allowBackup="true" 
    android:icon="@mipmap/ic_launcher" 
    android:label="@string/app_name" 
    android:largeHeap="true" 
    android:supportsRtl="true" 
    android:theme="@style/AppTheme"> 

無論您的應用程序的進程應該有大的Dalvik堆創建。這適用於爲應用程序創建的所有進程。它只適用於加載到進程中的第一個應用程序;如果您使用共享用戶ID來允許多個應用程序使用某個進程,則他們都必須始終使用此選項,否則將會產生不可預知的結果。 大多數應用程序不應該需要此功能,而應該專注於減少整體內存使用量以提高性能。啓用此功能也不能保證可用內存的固定增加,因爲某些設備受其可用內存總量的限制。

要在運行時查詢可用內存大小,請使用方法getMemoryClass()getLargeMemoryClass()


你會得到什麼:

  • 很明顯,你會得到更大的堆,這意味着減少的OutOfMemoryError風險。

什麼你減肥:

  • 你可能會失去一些幀,這可能會導致一個明顯的拖掛。較大的堆使垃圾收集需要更長的時間。因爲垃圾收集器基本上必須遍歷整個活動的對象集合。通常,垃圾收集暫停時間約爲5ms,您可能認爲幾毫秒不是什麼大問題。但每一毫秒都算。 Android設備必須每隔16 ms更新其屏幕,並且更長的GC時間可能會將幀處理時間推到16毫秒的屏障上,這可能會導致可見的掛接。

  • 此外切換應用程序將變得更慢。Android系統可能會終止LRU緩存中的進程,從最近最少使用的進程開始,但也會考慮哪些進程的內存密集度最高。因此,如果您使用較大的堆,那麼當您的進程停止後,您的進程將更有可能被殺死,這意味着用戶想要從其他應用切換到您的時間可能需要較長的時間。另外,當您的進程處於前臺時,其他後臺進程將更有可能被踢出,因爲您的應用需要更大的內存。這意味着從您的應用切換到其他應用也需要更長的時間。

結論:

避免使用largeHeap選項儘可能。這可能會讓您難以注意到性能下降和用戶體驗不佳。


讓我們得到更多更深圖像採集:

例如,它不值得載入1024×768像素的圖片到內存中,如果它最終將在ImageView顯示在128x96像素的縮略圖。

要告訴解碼器對圖像進行二次採樣,請將較小的版本加載到內存中,在您的BitmapFactory.Options對象中將inSampleSize設置爲true。例如,分辨率爲2048x1536且用inSampleSize爲4解碼的圖像會生成大約512x384的位圖。將其加載到內存中使用0.75MB而不是12MB(假設位圖配置爲ARGB_8888)。這裏的計算樣本大小值是兩個基於目標寬度和高度的功率的方法:

public static int calculateInSampleSize(
     BitmapFactory.Options options, int reqWidth, int reqHeight) { 
    // Raw height and width of image 
    final int height = options.outHeight; 
    final int width = options.outWidth; 
    int inSampleSize = 1; 

    if (height > reqHeight || width > reqWidth) { 

     final int halfHeight = height/2; 
     final int halfWidth = width/2; 

     // Calculate the largest inSampleSize value that is a power of 2 and keeps both 
     // height and width larger than the requested height and width. 
     while ((halfHeight/inSampleSize) > reqHeight 
       && (halfWidth/inSampleSize) > reqWidth) { 
      inSampleSize *= 2; 
     } 
    } 

    return inSampleSize; 
} 

Note: A power of two value is calculated because the decoder uses a final value by rounding down to the nearest power of two, as per the inSampleSize documentation.

相關問題