【发布时间】:2016-04-30 13:39:26
【问题描述】:
我已经阅读了很多关于这个主题的主题,并尝试在我的代码中使用它们,但我仍然无法解决它。
我想要做什么: 就像 facebook 或任何其他从服务器下载包含图像的提要的应用程序一样,我也在做同样的事情并尝试在图像视图上显示提要和图像。
发生了什么: 我能够下载包含图像 URL 的提要(以 JSON 格式),并且能够在 ImageView 上显示它们。 在模拟器中,我的最大堆大小为 64MB。我在前 10 个提要中消耗了大约 30MB(不知道为什么,但这是我从 Android Studio 的 Android 监视器中的内存选项卡甚至在 Android 设备监视器中得到的)。 我的应用程序中有一个刷新按钮,它在删除之前填充的所有提要后重新加载相同的提要。我预计我会消耗相同的内存或更多。但与此相反,我的内存使用量增加到 42MB。因此,在刷新 3 到 4 次后,它会导致 OutOFMemory Execption。即使我一次加载下 10 个或 50 个提要,我也会遇到 OutOfMemory 异常。
我知道 facebook instagram 和更多这样的应用程序做同样的事情,但不确定他们如何实现代码来覆盖这种情况。
以下是我用于填充提要的代码
private void loadFeed(List<Feed> feedList)
{
Log.v(Constant.TAG,"Loading Feed in social feed page");
for(final Feed feed:feedList) {
LinearLayout feedBox = new LinearLayout(this);
feedBox.setOrientation(LinearLayout.VERTICAL);
FrameLayout profileDetailContainer= new FrameLayout(this);
LinearLayout profileDetailContainerParent=new LinearLayout(this);
LinearLayout profileDetailContainerChild=new LinearLayout(this);
profileDetailContainerChild.setOrientation(LinearLayout.VERTICAL);
ImageView imgProfile= new ImageView(this);
TextView txtDate= new TextView(this);
TextView txtName= new TextView(this);
ImageView imgProduct= new ImageView(this);
txtName.setText(feed.getUserFullName());
TextView txtDesciption= new TextView(this);
txtName.setTypeface(null, Typeface.BOLD);
if(feed.getDescription().length()>Constant.NUMBER_OF_DESCRIPTION_CHAR_SHOW_ON_RESULT)
{
txtDesciption.setText(feed.getDescription().substring(0,Constant.NUMBER_OF_DESCRIPTION_CHAR_SHOW_ON_RESULT)+"...");
}
else
txtDesciption.setText(feed.getDescription());
if(!IOUtil.fileExists(this,feed.getProductImageName())) {
WebRequest request = new WebRequest();
request.setUrl(Constant.ROOT_APPLICATION_URL_WITH_SEPARATOR + feed.getImgPath());
request.setParam(feed.getId() + "");
new ImageDownloadTask(this, true, feed.getProductImageName(), this).execute(request);
Log.v(Constant.TAG,"URL:"+Constant.ROOT_APPLICATION_URL_WITH_SEPARATOR+feed.getImgPath());
Picasso.with(getApplicationContext()).load(R.drawable.logo).into(imgProduct);
feedBox.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
ScreenUtility.alertException(v.getContext(),"Please wait untill product image loads");
}
});
PixyfiSession.save(feed.getId() + "", imgProduct);
PixyfiSession.save(feed.getId() + "_feed", feed);
}
else
{
ImageUtil.recycleIfPossible(imgProduct);
try {
imgProduct.setImageBitmap(ImageUtil.getLocalImage(feed.getProductImageName(),this));
FeedboxOnClickListener feedboxOnClickListener = new FeedboxOnClickListener(feed);
feedBox.setOnClickListener(feedboxOnClickListener);
} catch (FileNotFoundException e) {
Log.v(Constant.TAG,e.getMessage(),e);
}
}
if(FacebookUtil.localProfilePicExists(feed.getUserName(),this))
{
Bitmap profileImage= FacebookUtil.getLocalProfilePicture(feed.getUserName(),this);
imgProfile.setImageBitmap(profileImage);
}
else {
FacebookUtil.loadProfilePicture(feed.getUserName(),this,this);
PixyfiSession.save(feed.getUserName(),imgProfile);
imgProfile.setImageResource(R.drawable.profile);
}
try {
if(feed.getDate()==null) {
txtDate.setText(new SimpleDateFormat("dd MMM yyyy").format(new SimpleDateFormat("yyyy-MM-dd").parse(feed.getFeedDate())));
}
else {
txtDate.setText(new SimpleDateFormat("dd MMM yyyy").format(feed.getDate()));
}
} catch (ParseException e) {
Log.e(Constant.TAG,e.getMessage(),e);
}
LinearLayout.LayoutParams layoutParam= new LinearLayout.LayoutParams(140,140);
layoutParam.setMargins(5,5,0,0);
imgProfile.setLayoutParams(layoutParam);
layoutParam= new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,LinearLayout.LayoutParams.WRAP_CONTENT,Gravity.TOP|Gravity.LEFT);
layoutParam.setMargins(20,5,0,0);
txtName.setLayoutParams(layoutParam);
layoutParam= new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,LinearLayout.LayoutParams.WRAP_CONTENT,Gravity.LEFT);
layoutParam.setMargins(20,5,0,0);
txtDate.setLayoutParams(layoutParam);
profileDetailContainerParent.addView(imgProfile);
profileDetailContainerChild.addView(txtName);
profileDetailContainerChild.addView(txtDate);
profileDetailContainerParent.addView(profileDetailContainerChild);
feedBox.addView(profileDetailContainerParent);
LinearLayout.LayoutParams feedLayoutParam=new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.WRAP_CONTENT,Gravity.CENTER_VERTICAL);
feedLayoutParam.setMargins(5,5,5,5);
imgProduct.setLayoutParams(feedLayoutParam);
txtDesciption.setLayoutParams(feedLayoutParam);
feedBox.addView(txtDesciption);
feedBox.addView(imgProduct);
feedLayoutParam=new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.WRAP_CONTENT,Gravity.CENTER_VERTICAL);
feedLayoutParam.setMargins(0,5,0,5);
feedBox.setLayoutParams(feedLayoutParam);
feedBox.setBackgroundColor(Color.parseColor("#cccccc"));
PixyfiSession.save(feed.getId()+"_feedbox",feedBox);
imgProfile.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
PixyfiSession.save(Constant.SELECTED_USER_ID,feed.getUserName());
ScreenUtility.loadScreen(v.getContext(),UsersProfile.class,false);
}
});
this.feedContainer.addView(feedBox);
}
if(feedList.size()==Constant.FEED_SIZE_IN_ONE_REQUEST)
{
Button moreFeed= new Button(this);
moreFeed.setText("Load MOre Feed");
moreFeed.setOnClickListener(new MoreFeedButtonListener(this));
this.feedContainer.addView(moreFeed);
}
this.progressBar.setVisibility(View.INVISIBLE);
}
用于重新加载/刷新提要
this.currentPage=1;
this.recycleImages();
this.feedContainer.removeAllViews();
PixyfiSession.save(Constant.CURRENT_FEED_PAGE,this.currentPage);
this.progressBar.setVisibility(View.VISIBLE);
loadFeed();
recycleImages 方法:
private void recycleImages()
{
for(int i=0;i<this.feedContainer.getChildCount();i++)
{
if(this.feedContainer.getChildAt(i) instanceof ImageView)
{
ImageView view=(ImageView)this.feedContainer.getChildAt(i);
ImageUtil.recycleIfPossible(view);
}
}
}
如果您需要有关代码的更多详细信息,请告诉我。 还可以在 android 设备监视器中查看其他应用程序(如 facebook)的内存使用情况吗? 更新 ImageUtil.getLocalImage 方法
public static Bitmap getLocalImage(String imageName, Context context) throws FileNotFoundException
{
Bitmap bitmap=null;
InputStream is=null;
if(IOUtil.fileExists(context,imageName)) {
is = context.openFileInput(imageName);
bitmap= BitmapFactory.decodeStream(is);
}
else {
throw new FileNotFoundException("Image file doesn't exists");
}
return bitmap;
}
【问题讨论】:
-
UI 组件太多了,你应该增加布局,这样可以减少视图泄漏的机会。而且,如果您可以使用回收站视图,那将会很有帮助。
-
我不关注你。我正在动态添加视图,如果这就是膨胀布局的意思。你能再解释一下吗?
-
通过扩展布局均值,您应该在 xml 文件中定义布局,然后使用它。它将易于管理,recyclerview 将帮助您再次重用相同的视图,最终在提要加载期间使用更少的视图数
-
实际上观看次数我不知道。我一次收到 10 个提要,用户可以加载接下来的 10 个提要,我需要在同一活动/屏幕中显示这些提要。因此,我动态地创建了 10 个以上的布局/视图以添加到我的线性布局中。当用户重新填充提要时,我会从线性布局的提要容器中删除所有视图并开始添加新提要。
-
不,我的意思是 recyclerview ,替代列表视图检查链接developer.android.com/reference/android/support/v7/widget/…
标签: java android out-of-memory picasso