# android常见bug及解决方案总结
### 空指针
##### 解决方案
* 不确定对象在使用前先做是否为空判断
* 特别注意:fragment getActivity为null处理
### 数组越界
##### 解决方案
* 使用索引值获取对象值时,需判断索引值是否小于数据源大小
example:
```javascript
if (mData != null && mData.size() !=0 && i < mData.size()){
Obj obj = mData.get(i);
}
```
### ListView或RecycleView 更新数据源命令不同步
##### 解决方案
* 保证设置数据源和执行adapter.notifyDataSetChanged在同一个线程并且在Ui线程
example:
```javascript
adapter.setData(mData);
adapter.notifyDataSetChanged();
```
### Windows无页面附加(Unable to add window.....is your activity running?)
##### 解决方案
* 执行windows窗体Dialog或PopupWindow时,先判断当前页面是否销毁,若页面还在则可以执行窗体显示操作,可以通过全局变量或activity自定义堆栈管理判断当前页面是否销毁,在onDestory里面做关闭窗体操作并置空
example:
```javascript
@Override
protected void onDestroy() {
if (mDialog != null && mDialog.isShowing()){
mDialog.dismiss();
mDialog = null;
}
super.onDestroy();
}
```
### sqlite问题(数据库缺字段或执行过程异常)
##### 解决方案
升级sqlite方法里面添加字段处理,此时记得加入try catch处理方式,防止出现崩溃现象。
example:
```javascript
FinalDb.DaoConfig daoConfig = new FinalDb.DaoConfig();
daoConfig.setContext(this);
daoConfig.setDbName(ChatDao.DATABASE_NAME);
daoConfig.setDebug(true);
daoConfig.setDbVersion(ChatDao.DATABASE_VERSION_CODE);
daoConfig.setDbUpdateListener(new FinalDb.DbUpdateListener() {
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// 当之前版本的数据升级到新版版本的数据,我们需要给对应表增加新的字段
try {
// 添加字段has_appraised字段
db.execSQL(ChatDao.VERSION_3_SQL_ADD_COLUMN_HAS_PRAISED);
}
catch (Exception e){
e.printStackTrace();
}
try {
// 添加字段receiveDate字段
db.execSQL(ChatDao.VERSION_4_SQL_ADD_CLUMN_RECEIVE_DATE);
}
catch (Exception e){
e.printStackTrace();
}
}
});
FinalDb.create(daoConfig);
```
### OOM(内存溢出)
#### 情况一
处理bitmap资源不得当造成(压缩或者变换得到新bitmap)
##### 解决方案
采用try catch处理方式,若出现异常再做压缩,期间采用弱引用方式处理。
example:
```javascript
WeakReference<Bitmap> bitmapWeakReference;
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
try {
options.inJustDecodeBounds = true;
BitmapFactory.decodeFileDescriptor(fd, null, options);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth,
reqHeight);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
// 弱引用处理图片 add leibing 2016/12/8
bitmapWeakReference
= new WeakReference<Bitmap>(BitmapFactory.decodeFileDescriptor(fd, null, options));
if (bitmapWeakReference != null && bitmapWeakReference.get() != null)
return bitmapWeakReference.get();
}catch (OutOfMemoryError ex){
// 压缩图片指定值 add by leibing 2016/12/8
options.inSampleSize = options.inSampleSize + 4;
options.inJustDecodeBounds = false;
// 弱引用处理图片 add leibing 2016/12/8
bitmapWeakReference
= new WeakReference<Bitmap>(BitmapFactory.decodeFileDescriptor(fd, null, options));
if (bitmapWeakReference != null && bitmapWeakReference.get() != null)
return bitmapWeakReference.get();
}
```
#### 情况二
各种内存泄漏问题造成,主要有以下:
##### 单例造成的内存泄露
###### 解决方案
1、将该属性的引用方式改为弱引用;
2、如果传入Context,使用ApplicationContext;
example
泄漏代码片段
```javascript
// sington
private static InstanceClass instance;
// activity refer
private Context mContext;
/**
* set activity refer
* @author leibing
* @createTime 2016/12/9
* @lastModify 2016/12/9
* @param mContext activity refer
* @return
*/
public void setRefer(Context mContext){
this.mContext = mContext;
}
/**
* constructor
* @author leibing
* @createTime 2016/12/9
* @lastModify 2016/12/9
* @param
* @return
*/
private InstanceClass(){
}
/**
* sington
* @author leibing
* @createTime 2016/12/9
* @lastModify 2016/12/9
* @param
* @return
*/
public static InstanceClass getInstance(){
if (instance == null){
synchronized (InstanceClass.class){
if (instance == null)
instance = new InstanceClass();
}
}
return instance;
}
```
Solution:使用WeakReference
```javascript
// sington
private static InstanceClass instance;
// activity refer
private WeakReference<Context> mContextWeakRef;
/**
* set activity refer
* @author leibing
* @createTime 2016/12/9
* @lastModify 2016/12/9
* @param mContext activity refer
* @return
*/
public void setRefer(Context mContext){
mContextWeakRef = new WeakReference<Context>(mContext);
}
/**
* constructor
* @author leibing
* @createTime 2016/12/9
* @lastModify 2016/12/9
* @param
* @return
*/
private InstanceClass(){
}
/**
* sington
* @author leibing
* @createTime 2016/12/9
* @lastModify 2016/12/9
* @param
* @return
*/
public static InstanceClass getInstance(){
if (instance == null){
synchronized (InstanceClass.class){
if (instance == null)
instance = new InstanceClass();
}
}
return instance;
}
```
##### InnerClass匿名内部类
###### 解决方案
1、将内部类变成静态内部类;
2、如果有强引用Activity中的属性,则将该属性的引用方式改为弱引用;
3、在业务允许的情况下,当Activity执行onDestory时,结束这些耗时任务;
example
泄漏代码片段
```javascript
public class InnerClassActivity extends Activity{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// start a thread to work
new InnerThread().start();
}
/**
* @interfaceName: InnerThread
* @interfaceDescription: custom thread
* @author: leibing
* @createTime: 2016/12/9
*/
class InnerThread extends Thread{
@Override
public synchronized void start() {
super.start();
}
}
}
```
Solution:使用WeakReference + static
```javascript
public class InnerClassActivity extends Activity{
// 图片资源
private Drawable mDrawable;
// inner thread
private InnerThread mInnerThread;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// init drawable
mDrawable = getResources().getDrawable(R.drawable.ic_launcher);
// start a thread to work
mInnerThread = new InnerThread(mDrawable);
mInnerThread.start();
}
@Override
protected void onDestroy() {
if (mInnerThread != null)
mInnerThread.setIsRun(false);
super.onDestroy();
}
/**
* @interfaceName: InnerThread
* @interfaceDescription: custom thread
* @author: leibing
* @createTime: 2016/12/9
*/
static class InnerThread extends Thread{
// weak ref
public WeakReference<Drawable> mDrawableWeakRef;
// is r