网络上真的很难找到正在符合自己需求的东西,一晚上找了到一个和自己开发的项目类似的例子,在此转载过来,感谢作者无私的分享,原作者博客文章:http://my.oschina.net/banxi/blog/57984,
如果你正在找Android后台定时任务实现,那么你找对了,但是其实如果你正在找Java后台任务实现,你就不会找到我的这个博客了.但是我的实现方式没有使用多少Android相关的东西.确实.但是如果你进来了,Thank you!你还是会看到一些东西的.
一:需求: 我的一些数据一开始是从服务端读取出来的,但是随着时间的改变,我本地改变了一些数据.服务器的一些数据也发生了改变.一开始,但用户查看这些数据的时候,我再去服务器上将数据下载下来. 但是每次去下,有些数据变化不太.这个下载操作的的很大一部分就是白下载了.所以我开始探索解决方案:
二:解决方案:
(1) 下载前先检测服务端数据是否有发生了变化.数据库中的每一行记录都有一个字段标识数据是否发生改变了的时间.
于是先下载数据库记录最后改变时间. 我用前次下载得来的最后改变时间与当前下载得的时间对比.如果下载回来的时间大于我原来存储的时间.那么我便决定去下载数据....就这样它一直工作着.. 我觉得这样可以了.
但是,后来出现了数据没有同步的问题.因为有些对于数据记录的操作并没有改变那个标识了时间改变的字段.
所以方法失效.
(2)保证所以操作都改变时间标识字段.
这个方法有几点行不通,这个应用本身是从原来已经有的应用移植.所以服务端的后台数据库不能轻易改变.改变了也比较难以保证所以用户得及时更新的服务器中后台数据库.
最关键的是如果后台数据更新频繁,事实上我们的应用就是这样的.那么检测更新没有多大意义.因为几乎每次检测的结果都是需要更新. 在更新这个时间里,因为网络不稳定问题.用户等待时间太久.用户体验就明显下降了.这个检测更新也就完全没有什么意义了.
(3) 目前解决办法.
使用一个后台线程以一个比较合理的频率定时更新数据.
针对后台线程,由于做android开发的习惯.我们可能会想到使用Service.
但是真的需要Service吗?一开始我尝试这样,于是开始找Service的资料.我承认我对Service不熟悉...
我只使用绑定本地Service的方法,每次Activity创建就会重新绑定一次.但那没有关系.因为当时那个LocalService是读取SQLite数据库中的数据了.而且只读取一次放到缓存中(其实就是内存).
但是通过绑定的方法每次Activity启动等都会创建然后销毁服务.于是我就不想要了..
我希望我的应用启动前开始我的后台线程,结束时取消后台线程..仅此而已.于是我找其它的方式.如startService和stopService等方式,及为了让服务不被Android给杀掉可以把服务设置为前台服务.
但是,后台线程,为什么一定要用Service呢?我想,我所要进行的操作根据不需要Service.
还记得没有,想要在应用中全局共享变量,一个方法就是给应用设置一个自己子类化的Application.
但是,我看文档时发现,其实如果没有必要你根本可以使用一个静态单例来实现类似Application子类的功能.
我是比较听说的人,所以我就按文档要求的,自己实现静态单例了.需要使用Context的方法传进去就是了.
说了这么多,其实就是说,我们完全可以不用理会Service,应用就是在本地应用中使用.在自己的静态单例中实现就可以了.
而我确实也是这样做的.
在应用的主Activity的onCreate()方法中开始后台线程的执行.在此Activity的onDestory()方法中.结束后台线程的执行.
OK,满足需求了.
关键代码如下 :
01 | public static void startSyncTableStauts( int seconds) { |
02 | TimerTask timerTask = new TableStatusSyncTimerTask(); |
03 | timer = new Timer( true ); |
04 | timer.scheduleAtFixedRate(timerTask, 100 , seconds * 1000 ); |
07 | public static void stopSyncTableStatus() { |
13 | private static class TableStatusSyncTimerTask extends TimerTask { |
17 | if (cachedFloors.size() < 1 ) { |
19 | setFloors(FloorDao.findAll()); |
20 | } catch (TcpException e) { |
26 | for (Floor floor : cachedFloors) { |
29 | List<Table> tables = TableDao.findByFloorId(floor.id); |
30 | statusMap.put(floor.id, false ); |
31 | for (Table table : tables) { |
32 | String key = floor.id + "#" + table.getTabid(); |
33 | cachedTables.put(key, table); |
35 | statusMap.put(floor.id, true ); |
36 | Log.i( "DiApplication" , " finish update table in floor:" |
38 | } catch (TcpException e) { |
49 | public static synchronized void setFloors(List<Floor> floors) { |
52 | cachedFloors.addAll(floors); |
为什么要使用同步,因为我执行的是网络操作,如果后台线程还没有取回数据.我在前台程序中,就会自己主动去下载数据.
(为什么不等待数据有的时候. 因为如果网络出错.还是在前台程序中处理比较好.要让用户看到.) 下载好之后就将数据放到缓存中,因为是用List的所以不想出现线程问题所以就用同步了...
整个对于缓存的使用的应用代码也是放在AsyncTask内的doInBackground()内中去的.所以应用体验就比较好的.
暂时写到这里.如什么不正确的地方请各位同学指出来哈!