关于应用中过多的imageView和listView导致的不定时的oom(主要是bitmap 被VM buget 限制)和电子书的实现

网上流传的关于bitmap内存泄漏的解决方案,都是两种 : 1.减小图片的大小,即使用options.insampesize,但是还是不能彻底的解决偶尔的oom。2.去掉bitmap被指向的引用,让system.gc来处理这个问题,但是bitmap是在native层分配内存,而且在多个activity存在得应用中无法根本上除掉bitmap得引用(除非再程序一开始时,成员都规定再onDestory里除掉再本activity里对bitmap的引用,可以得到,这是个教训),幸好bitmap提供了一个recycle的方法,让java可以主动的让native层的bitmap释放空间(这个方法解决了我的问题)。


再次说到我们这次遇到oom的问题,开始使用 eclipse自带的leap查看堆大小的使用,完全没有达到24M或8M就抛出oom,网上说的8MBitmap内存限制到我现在看来,感觉不是很靠谱,因为linux采用的内存策略是和硬盘交换的,所以理论上说(看别人写的)没有准确的内存计算,而eclipse看到的只是DVM的大小无法显示C++层的内存。所以使用adb shell 工具

 adb shell "dumpsys meminfo com.package.name" 可以查看到大部分需要看到的内存。使用了这个工具才看到我的应用里70%都是再native里的分配的,而且神奇的是我的中内存出现了25M的情况,不知道这个情况是通过linux内存无法准确计算解释,或者 24M是胡人的。 通过这次的OOM,重新搞了一个线程池,来管理下载线程,使打印信息更容易排错,重构了activity的基类,使用Application类实现一些程序的初始化。


下面写程序里比较蛋疼的错误解释:

/**
 * 因为activity的生命周期在启动下一个activity时(this表示当前activity,next表示下一个需要启动的activity):this.onPause->next.oncreate->next.onstart->next.onresume->this.onStop->this.onDestory
 * 关闭当前activity回到上一个activity(this表示当前activity,pre表示上一个需要启动的activity):this.onPause->pre.onrestart->pre.onstart->pre.onresume->this.onstop->this.ondestroy
 * 所以在onDestroy里recycle Bitmap,上一个activity先引用了没有回收的bitmap,但是onDestroy才被调用了,故在对当前的activity操作就会出现使用被回收的bitmap的错误
 * 又由于返回上一个activity只是单纯得把压入栈里的activity实例拿出来(这个表达的是:一个listView经过onCreat方法画好,进入onstop状态,等待它回来时不会重新去adapter里getView方法重绘,直接再内存块里拿出之前的数据画。)
 * 
 * @author demo
 *
 */


在电子书中实现绘图:图片大小 分辨率 长*宽*Config.模式 = 图片大小 ------------------------->480*800*Config.argb8888 = 480*800*4 = 1536000B = 1.5M

由于需要 两张 图片 才能作出 翻页效果 故 1.5M*2 = 3M ,加上一个drawable里存放的背景,需要打开一个应用里的电子书需要大概 5M得内存分配,由于应用其他地方使用了过多的内存没有释放,无法打开 电子书功能。电子书里实现 加粗某些文字,跳转到指定位置。由于是通过XML解析出目录和内容和加粗,都是通过记录 该跳转的开始位置实现。


以上为一部分总结,有时间再补充。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面是一个简单的应用市场APP的实现步骤和代码示例: 1. 创建一个新的Android项目,并在布局文件中添加一个ListView控件。 2. 创建一个数组来存储应用市场中的应用信息,比如应用名称、图标、描述等。 3. 创建一个自定义的Adapter来将应用信息显示在ListView中。Adapter需要实现以下方法: - getCount():返回要显示的项数。 - getItem():返回指定位置的应用信息。 - getItemId():返回指定位置的应用信息的ID。 - getView():返回指定位置的应用信息的视图。 4. 在Activity中将Adapter设置为ListView的适配器。 5. 在getView()方法中,使用布局文件中定义的视图来显示应用信息。可以使用LayoutInflater来加载布局文件。 下面是一个简单的应用市场APP的代码示例: MainActivity.java ``` public class MainActivity extends AppCompatActivity { ListView listView; String[] appNames = {"应用1", "应用2", "应用3"}; int[] appIcons = {R.drawable.app1_icon, R.drawable.app2_icon, R.drawable.app3_icon}; String[] appDescriptions = {"这是应用1的描述", "这是应用2的描述", "这是应用3的描述"}; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); listView = findViewById(R.id.list_view); AppListAdapter adapter = new AppListAdapter(this, appNames, appIcons, appDescriptions); listView.setAdapter(adapter); } } ``` AppListAdapter.java ``` public class AppListAdapter extends BaseAdapter { Context context; String[] appNames; int[] appIcons; String[] appDescriptions; public AppListAdapter(Context context, String[] appNames, int[] appIcons, String[] appDescriptions) { this.context = context; this.appNames = appNames; this.appIcons = appIcons; this.appDescriptions = appDescriptions; } @Override public int getCount() { return appNames.length; } @Override public Object getItem(int position) { return appNames[position]; } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); convertView = inflater.inflate(R.layout.item_app, null); ImageView appIcon = convertView.findViewById(R.id.app_icon); TextView appName = convertView.findViewById(R.id.app_name); TextView appDescription = convertView.findViewById(R.id.app_description); appIcon.setImageResource(appIcons[position]); appName.setText(appNames[position]); appDescription.setText(appDescriptions[position]); return convertView; } } ``` item_app.xml ``` <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content"> <ImageView android:id="@+id/app_icon" android:layout_width="64dp" android:layout_height="64dp" android:layout_margin="16dp" /> <TextView android:id="@+id/app_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_toRightOf="@id/app_icon" android:textSize="24sp" android:textStyle="bold" android:layout_marginTop="16dp" android:layout_marginLeft="16dp"/> <TextView android:id="@+id/app_description" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/app_name" android:layout_toRightOf="@id/app_icon" android:layout_marginTop="16dp" android:layout_marginLeft="16dp"/> </RelativeLayout> ``` 上面的代码实现了一个简单的应用市场APP,使用ListView控件来显示应用信息。你可以根据自己的需求来修改和扩展此代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值