您的位置:首页 > 移动开发

第二阶段 7、添加数据库逻辑,防止App被强杀后的数据丢失

2016-01-15 13:55 363 查看
应用场景:

场景一:退出应用,任务在后台服务中执行,再次进入应用时,显示的数据会不同步。

场景二:下载数据存在内存中,当应用被强杀后,再次进入应用时,数据会被清空。

解决思路:

场景一:上一阶段中创建的mOperatedEntries集合中保存的是所有被操作过的最新的下载Entry,可在onCreate()方法中将当前显示的entry的最新状态从mOperatedEntries集合中提取出来。

场景二:既然存储在内存中会被清除,那就存储在数据库中,每次Entry的状态改变时,除去往mOperatedEntries集合中存储之外,还要往数据库中存储一份,而调用时只在创建DownloadService时调用一次,即只在Service类中的onCreate()方法中调用一次

解决方案:

场景一的解决方案

1、DataChanger

// 创建queryDownloadEntryById(String id)方法,通过该方法可从mOperatedEntries集合中取出所需的Entry
public DownloadEntry queryDownloadEntryById(String id) {
return mOperatedEntries.get(id);
}


2、DownloadManager

// 调用DantaChanger中的queryDownloadEntryById方法,提供给外部使用
public DownloadEntry queryDownloadEntry(String id) {
return DataChanger.getInstance(context).queryDownloadEntryById(id);
}


3、ListActivity

// onCreate()方法中在创建完所需的下载Entry之后,根据创建的Entry的id,从mDownloadEntries中取出最新状态的Entry,在对应位置替换掉
DownloadEntry entry = null;
DownloadEntry realEntry = null;
for (int i = 0; i < mDownloadEntries.size(); i++) {
entry  = mDownloadEntries.get(i);
realEntry = mDownloadManager.queryDownloadEntry(entry.id);
if (realEntry != null) {
mDownloadEntries.remove(i);
mDownloadEntries.add(i, realEntry);
}
}


场景二的解决方案:

1、OrmDBHelper

// 创建数据库助手类
public class OrmDBHelper extends OrmLiteSqliteOpenHelper{
public static final String DB_NAME = "fsf_downloader";
public static final int DB_VERSION = 1;

public OrmDBHelper(Context context, String databaseName,
CursorFactory factory, int databaseVersion) {
super(context, databaseName, factory, databaseVersion);
}

public OrmDBHelper(Context context) {
super(context, DB_NAME, null, DB_VERSION);
}

@Override
public void onCreate(SQLiteDatabase database, ConnectionSource connectionSource) {
try {
TableUtils.createTable(connectionSource, DownloadEntry.class);
} catch (SQLException e) {
e.printStackTrace();
}
}

@Override
public void onUpgrade(SQLiteDatabase arg0, ConnectionSource arg1, int arg2, int arg3) {

}

}


2、DBController

创建数据库控制类

public class DBController {
private static DBController instance;
private SQLiteDatabase mDB;
private OrmDBHelper mDBhelper;

private DBController(Context context) {
mDBhelper = new OrmDBHelper(context);
mDB = mDBhelper.getWritableDatabase();
}

public static DBController getInstance(Context context) {
if (instance == null) {
instance = new DBController(context);
}
return instance;
}

public synchronized void newOrUpdate(DownloadEntry entry) {
try {
Dao<DownloadEntry, String> dao = mDBhelper
.getDao(DownloadEntry.class);
dao.createOrUpdate(entry);
} catch (SQLException e) {
e.printStackTrace();
}
}

public synchronized ArrayList<DownloadEntry> queryAll() {
Dao<DownloadEntry, String> dao;
try {
dao = mDBhelper.getDao(DownloadEntry.class);
return (ArrayList<DownloadEntry>) dao.query(dao.queryBuilder()
.prepare());
} catch (SQLException e) {
Trace.e(e.getMessage());
return null;
}
}

public synchronized DownloadEntry queryById(String id) {
try {
Dao<DownloadEntry, String> dao = mDBhelper.getDao(DownloadEntry.class);
return dao.queryForId(id);
} catch (SQLException e) {
Trace.e(e.getMessage());
return null;
}
}
}


3、DownloadEntry

@DatabaseTable(tableName = "downloadentry")
public class DownloadEntry implements Serializable {
@DatabaseField(id = true)
public String id;
@DatabaseField
public String name;
@DatabaseField
public String url;
@DatabaseField
public DownloadStatus status = DownloadStatus.idle;
@DatabaseField
public int currentLength;
@DatabaseField
public int totalLength;
public DownloadEntry() {
}
public DownloadEntry(String url) {
this.url = url;
this.name = url.substring(url.lastIndexOf("/") + 1);
}
public enum DownloadStatus {
idle, waiting, downloading, paused, resumed, cancelled, completed
}
@Override
public String toString() {
return "DownloadEntry: " + url + " is " + status.name() + " with "
+ currentLength + "/" + totalLength;
}
@
c2f5
Override
public boolean equals(Object o) {
return o.hashCode() == this.hashCode();
}
@Override
public int hashCode() {
return id.hashCode();
}
}


4、DataChanger

// 将最新状态的Entry存入mOperatedEntries之后,再存入本地数据库
public void postStatus(DownloadEntry entry) {
mOperatedEntries.put(entry.id, entry);
DBController.getInstance(context).newOrUpdate(entry);
setChanged();
notifyObservers(entry);
}


5、DownloadService

// 创建服务的同时,创建数据库
@Override
public void onCreate() {
super.onCreate();
mExecutors = Executors.newCachedThreadPool();
mDataChanger = DataChanger.getInstance(getApplicationContext());
mDBController = DBController.getInstance(getApplicationContext());
// 取出数据库中存储的Entry
ArrayList<DownloadEntry> mDownloadEntries = mDBController.queryAll();
if (mDownloadEntries != null) {
for (DownloadEntry entry : mDownloadEntries) {
// 重新创建服务后,所有的任务都要处于静止状态,然后再一次加入下载集合中
if (entry.status == DownloadEntry.DownloadStatus.downloading || entry.status == DownloadEntry.DownloadStatus.waiting)      {
entry.status = DownloadEntry.DownloadStatus.paused;
// TODO add a config if need to recover download
// 加入到下载队列中
addDownload(entry);
}
// 更新mOperatedEntries集合
mDataChanger.addToOperatedEntryMap(entry.id, entry);
}
}
}


6、SplashActivity

// 优化:将DownloadManager放到闪屏页初始化
public class SplashActivity extends Activity{
@SuppressLint("HandlerLeak")
private Handler mHandler = new Handler() {
public void handleMessage(android.os.Message msg) {
jumpTo();
};
};

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
DownloadManager.getInstance(getApplicationContext());
mHandler.sendEmptyMessageDelayed(0, 2000);
}

private void jumpTo() {
Intent intent = new Intent(this, ListActivity.class);
startActivity(intent);
}
}


相关知识来源:

stay老兄的有心课堂-自己动手写多任务下载框架
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  数据库 app