我正在创建一个通过发出http请求来获取json数据的应用程序,在解析该数据之后,它会在布局中填充视图,还将该json数据存储在列表数据集合中的字符串中。在布局中有一个用Picasso填充的图像视图,最后我在ViewPager 中有两个片段。每个片段都有分页来加载更多数据,并通过获取json数据填充结果列表对于每个页面。
我也必须
将http json响应存储到列表和两个片段
回收站查看堆中两个片段的适配器。
<小时/> 加载更多列表数据时遇到了以下胎儿错误。
Process: mashhood.meshsoft.com.gn_news, PID: 18465
java.lang.OutOfMemoryError: Failed to allocate a 94784012 byte allocation with 4194304 free bytes and 87MB until OOM
at dalvik.system.VMRuntime.newNonMovableArray(Native Method)
at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:655)
at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:483)
at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:1157)
at android.content.res.ResourcesImpl.loadDrawableForCookie(ResourcesImpl.java:720)
at android.content.res.ResourcesImpl.loadDrawable(ResourcesImpl.java:571)
at android.content.res.Resources.loadDrawable(Resources.java:972)
at android.content.res.TypedArray.getDrawable(TypedArray.java:931)
at android.widget.ImageView.<init>(ImageView.java:157)
at android.widget.ImageView.<init>(ImageView.java:145)
at android.support.v7.widget.AppCompatImageView.<init>(AppCompatImageView.java:60)
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:1029)
at android.support.v7.app.AppCompatDelegateImplV9.onCreateView(AppCompatDelegateImplV9.java:1087)
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 mashhood.meshsoft.com.gn_news.movies.Adapters.RecyclerViewAdapters.RecyclerViewForMoiveDiscovery.onCreateViewHolder(RecyclerViewForMoiveDiscovery.java:74)
at mashhood.meshsoft.com.gn_news.movies.Adapters.RecyclerViewAdapters.RecyclerViewForMoiveDiscovery.onCreateViewHolder(RecyclerViewForMoiveDiscovery.java:39)
at android.support.v7.widget.RecyclerView$Adapter.createViewHolder(RecyclerView.java:6367)
at android.support.v7.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:5555)
at android.support.v7.widget.GapWorker.prefetchPositionWithDeadline(GapWorker.java:282)
at android.support.v7.widget.GapWorker.flushTaskWithDeadline(GapWorker.java:336)
at android.support.v7.widget.GapWorker.flushTasksWithDeadline(GapWorker.java:349)
at android.support.v7.widget.GapWorker.prefetch(GapWorker.java:356)
at android.support.v7.widget.GapWorker.run(GapWorker.java:387)
at android.os.Handler.handleCallback(Handler.java:836)
at android.os.Handler.dispatchMessage(Handler.java:103)
at android.os.Looper.loop(Looper.java:203)
at android.app.ActivityThread.main(ActivityThread.java:6251)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1063)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:924)
<小时/> 适用于RecyclerView的适配器如下
/**
* Created by Mashhood on 3/14/2018.
*/
public class RecyclerViewForMoiveDiscovery extends RecyclerView.Adapter<RecyclerViewForMoiveDiscovery.MyViewHolder> {
//this is for the class fields
public Context ctx;
public List<DiscoverMovies> list; //this is for the list of items
//end of the class fields as it should be
//this is for the holder for the thread reasoning
public Handler handler; //this is for the handler to handle ui thread
//end of the holder for the thread reasoning
//this is for the constructor
public RecyclerViewForMoiveDiscovery(Context context,List<DiscoverMovies>list){
this.ctx=context; //this is for context
this.list=list; //this is for the list
//this is for the initialization of handler
handler=new Handler(); //this is for the handler
//end of initialization for handler
}
//end of the constructor
//this is for the RecyclerView Methods
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
//this is for the LayoutInFlator
LayoutInflater layoutInflater=LayoutInflater.from(parent.getContext());
View view=layoutInflater.inflate(R.layout.movie_item,parent,false);
//end of the LayoutInFlator
//this is to create the view holder
MyViewHolder myViewHolder=new MyViewHolder(view);
//end of view holder
return myViewHolder; //this is for myViewHolder
}
@Override
public void onBindViewHolder(final MyViewHolder holder, int position) {
try{
final DiscoverMovies discoverMovies=list.get(holder.getAdapterPosition()); //this is for getting current object
//now to place it in views
holder.movie_rating.setText(discoverMovies.getVoteAverage()); //this is for average vote
holder.movie_name.setText(discoverMovies.getTitle()); //this is for the movie name
holder.movie_year.setText(discoverMovies.getRelease_date()); //this is for the release date
holder.overview_text.setText(discoverMovies.getOverview()); //this is for the overview for movies
//end of the placement
try{
//this is for the picasso work to get the image
Picasso.with(this.ctx).load(discoverMovies.getPoster_path()).error(R.drawable.moive_item_background).into(holder.picture);
//end of the picasso work to get the image
}
catch (Exception ex){
LogPrinting("Exception of type "+ex.getMessage()+"while loading the Image");
}//end of loading the Picture
//this is for the click listener for the watch trailer button
holder.watch_trailer_button.setOnClickListener(new View.OnClickListener() {
public final String movie_id=discoverMovies.getId(); //this is for getting the movie id
@Override
public void onClick(View v) {
if(isOnline()){
FindVideoIdForThatMovie(movie_id); //this is for finding the movie trailer
} //this is for the if
else{
ToastPrinting("Please get Internet Connection");
}//end of else
}
});
//end of the block for the click listener for the watch trailer button
//this is for the holder watch movie button
holder.watch_movie_button.setOnClickListener(new View.OnClickListener() {
public final String movie_id=discoverMovies.getId(); //this is for the movie id
@Override
public void onClick(View v) {
try{
if(isOnline())
{
Intent i=new Intent(ctx, MoviePlayer.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); //this is for the new task
Bundle b=new Bundle();
b.putString("id",movie_id);
i.putExtras(b);
ctx.startActivity(i);
}
else{
ToastPrinting("Please get a Internet Connection");
}
} //end of the try
catch (Exception ex){
LogPrinting("Exception of type is as follows "+ex.getMessage());
}//end of the catch
}
});
//end of watch movie button
}//end of the try
catch(Exception ex){
LogPrinting("Exception while binding the Values with view items "+ex.getMessage());
}//end of catch
} // end of the OnBindViewHolder
@Override
public int getItemCount() {
return list.size(); //this is for the list Size
}
//end of RecyclerView Methods
//this is for the Log and Toast printing
private static final String TAG = "RecyclerViewForMoiveDis";
public void LogPrinting(String Line){
Log.d(TAG,Line); //this is for the Log Printing
}//this is for Log
public void ToastPrinting(String Line){
Toast.makeText(this.ctx,Line,Toast.LENGTH_SHORT).show();
}//end of Toast
//end of Log And Toast Printing
//this is for the ViewHolder
class MyViewHolder extends RecyclerView.ViewHolder{
//this is for the class fields
public View view; //this is for the view
// this is for the public view
public TextView movie_rating; //this is for the movie_rating
public TextView movie_name; //this is for the movie name
public TextView movie_year; //this is for the movie year
public TextView overview_text; //this is for the movie overview
public Button watch_trailer_button ; //this is for the trailer
public Button watch_movie_button; //this is to watch movie
public ImageView picture; //this is for the picture
//end of the public view
//end of view items
public MyViewHolder(View itemView) {
super(itemView);
view=itemView;
InitializeComponents(); //this is to initialize the components
}
//end of the class fields
//this is for the initialization of the components
public void InitializeComponents(){
try{
movie_rating=(TextView) view.findViewById(R.id.movie_rating); //this is for rating
movie_name=(TextView) view.findViewById(R.id.movie_name); //this is for the movie name
movie_year=(TextView) view.findViewById(R.id.movie_year); //this is for the movie year
overview_text=(TextView) view.findViewById(R.id.overview_text); //this is for overview text
watch_trailer_button=(Button) view.findViewById(R.id.watch_trailer_button); //this is for watch trailer button
watch_movie_button=(Button) view.findViewById(R.id.watch_movie_button); //watch movie button
picture=(ImageView) view.findViewById(R.id.movie_picture); //this is for the movie picture
}//end of the try
catch (Exception ex){
LogPrinting("Exception of type is as follows "+ex.getMessage());
}//end of catch
}
//end of the initialization of the components
}
//end of the ViewHolder
//this is for loading the video id for a given movie
public void FindVideoIdForThatMovie(final String movieId){
try{
//there we will make the http request for that page
Thread t=new Thread(new Runnable() {
@Override
public void run() {
//inner try catch
try{
URL url=new URL(new UrlData().GiveMeUrlForVideo(movieId)); //this is for the url
URLConnection urlConnection=url.openConnection(); //this is to open http connection
BufferedReader bufferedReader=new BufferedReader(new InputStreamReader(urlConnection.getInputStream())); //this is for the buffered reader
String Line=""; //this is for the Line
String temporary_line=""; //this is for the temporary line
//this is for the loop to get the data
while((temporary_line=bufferedReader.readLine())!=null){ //keep on reading the Line till no line
Line +=temporary_line; //this is for the temporary Line
} //end of the loop to get the data
//to print what we have got
LogPrinting("Coming Video data is as \n"+Line); //this is for the Line
//end of printing what we have got
//this is for the parsing phase
try{
JSONObject mainJSONObject=new JSONObject(Line); //this is for main JSONObject
JSONArray jsonArray=mainJSONObject.getJSONArray("results"); //this is for getting the json array
JSONObject very_first_object=(JSONObject) jsonArray.get(0); //this is for json array
final String youtube_video_id= very_first_object.get("key").toString(); //this is for the youtube video id
//now we have to code for sending that video id to new youtube activity
handler.post(new Runnable() {
@Override
public void run() {
try{
Intent i=new Intent(ctx, YouTubePlayerActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); //this is for the new task
Bundle b=new Bundle();
b.putString("id",youtube_video_id);
i.putExtras(b);
ctx.startActivity(i);
}//end of try
catch (Exception ex3){
LogPrinting("Exception while opening the youtube activity "+ex3.getMessage());
}
}
});
//end of the activity for sending that video id to new youtube activity
}//end of try block
catch (Exception exi){
LogPrinting("Exception of type "+exi.getMessage()+" while parsing the json data for videos");
}
//end of the parsing phase
}//end of try
catch (Exception ex){
LogPrinting("Exception of type "+ex.getMessage()+" while loading the videos data for that job ");
}
//end of inner try catch
}
}); //end of Thread
t.start();
//end of making the http request for that page
}//end of the try block
catch (Exception ex){
LogPrinting("Exception of type "+ex.getMessage()+" while loading the video id from source in Recycler Adapter for Movies");
}//end of the catch block for loading the movies from movies sources
}
//end of loading the video id for a given movie
//this is for checking either the user is online
public boolean isOnline() {
ConnectivityManager cm = (ConnectivityManager) this.ctx.getSystemService(ctx.CONNECTIVITY_SERVICE);
return cm.getActiveNetworkInfo() != null && cm.getActiveNetworkInfo().isConnectedOrConnecting();
}
//end of checking either user is online or not
}//end of the class
答案 0 :(得分:1)
当dalvik VM拒绝允许分配更多内存资源时,会发生OutOfMemoryError。正如所讨论的问题,使用名为 RecyclerViewForMoiveDiscovery 的RecyclerViewAdapter中的Picasso从远程主机加载大量图像。甚至完成活动后,位图保留在内存中,导致大量内存使用,直到导致OutOfMemoryError。在研究了类似类型的不同案例之后,我知道我们可以在使用毕加索时选择以下。
我们应该设置一个stableKey ,同时将url设置为picasso以获取图片。
Picasso.with(上下文).load(IMAGE_URL).stableKey(stable_key).into(holder.picture);
on Activity destroy 我们必须通过提供 stableKey 来使该文件无效,如下所示
Picasso.with(context).invalidate(stable_key);
NetworkPolicy.NO_CACHE
这样做我使用以下代码Picasso.with(context).load(path).skipMemoryCache().networkPolicy(NetworkPolicy.NO_CACHE).error(R.drawable.default_image).into(imageView);
这是阻止缓存的更好方法但毕加索启动花费更多时间加载图片。android:largeHeap="true"
来提出请求。这是一种更简单的方法,但不好,因为如果我们这样做,它可能导致内存泄漏。有效的方法是通过使用Runtime.getRuntime.gc()
使内存不受动态分配的对象的影响来管理堆。