从网络获取数据(1)从newThread到AsyncTask在到IntentService
来源:互联网 发布:php echo 编辑:程序博客网 时间:2024/06/16 13:51
概述
安卓不允许在UI线程中发送网络请求,因此必须新启动一个线程。
如果我们在活动中new Thread,这样就会有问题,这个线程会随着活动的生命周期结束而结束,如果活动的命比这个线程短,活动死掉了,线程还没有进行完,然后也不幸
挂了,这样,获取数据的任务就相当于是失败了,这肯定是不可以的啊。所以我们需要使用一个后台进程,比如AsyncTask,但是这个AsyncTask也要能快速完成(最多几秒),
不过他也有的一个问题就是,如果用户选择屏幕,后台的那个AsyncTask没有执行完,又会新建一个AsyncTask,这就导致资源的浪费了,不过应该问题不大,我们还是要知道
这个AsyncTask的。最后就是IntentService,系统会根据情况停止IntentService。下面来一个个讲
实现AsyncTask
AsyncTask must be subclassed to be used. The subclass will override at least one method (
doInBackground(Params...)
), and most often will override a second one (onPostExecute(Result)
.)private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> { protected Long doInBackground(URL... urls) { int count = urls.length; long totalSize = 0; for (int i = 0; i < count; i++) { totalSize += Downloader.downloadFile(urls[i]); publishProgress((int) ((i / (float) count) * 100)); // Escape early if cancel() is called if (isCancelled()) break; } return totalSize; } protected void onProgressUpdate(Integer... progress) { setProgressPercent(progress[0]); } protected void onPostExecute(Long result) { showDialog("Downloaded " + result + " bytes"); } }这样使用:
new DownloadFilesTask().execute(url1, url2, url3);我们在sunshine工程中也新建了一个FetchWeatherTask
publicclassFetchWeatherTaskextendsAsyncTask<String,Void,Void> {}
第一个参数是String,传递是一个地理位置id,第二个第三个不需要,Void,下面是调用:
private void updateWeather() {
FetchWeatherTask weatherTask = new FetchWeatherTask(getActivity());
String location = Utility.getPreferredLocation(getActivity());
weatherTask.execute(location);
}
FetchWeatherTask weatherTask = new FetchWeatherTask(getActivity());
String location = Utility.getPreferredLocation(getActivity());
weatherTask.execute(location);
}
在doInBackground中执行查询,然后解析json,批量插入插入数据库。
其实也挺简单的。
IntentService
这就是服务的使用了。安卓系统提供了两种实现,
直接继承Service:我们需要启动一个新线程来执行我们的操作,因为默认服务使用主线程,会影响活动的表现
继承IntentService:
使用一个工作线程处理请求,一次一个。
如果我们不需要同时处理多个请求,实现IntentService是一个好选择,只需要实现onHandleIntent()方法,传递一个Intent,就在后台工作了。
IntentService做了下面的事:
• 创建一个默认的工作线程执行所以传递给onStartCommand的intents独立于应用的主线程(新的线程了,所以不会干扰,那还说我自己要新启线程,应该是直接Service需要)
• 创建一个工作序列,一次传递一个intent给onHandleIntent实现,所以永远不用担心多线程
• 所有的开启请求被处理完之后停止服务,所以永远不用调用stopSelf
• 提供onBind的默认实现,返回null
• 提供onStartCommand的默认实现,这个方法发送intent给工作序列,然后发送intent给onHandleIntent实现。
• 创建一个默认的工作线程执行所以传递给onStartCommand的intents独立于应用的主线程(新的线程了,所以不会干扰,那还说我自己要新启线程,应该是直接Service需要)
• 创建一个工作序列,一次传递一个intent给onHandleIntent实现,所以永远不用担心多线程
• 所有的开启请求被处理完之后停止服务,所以永远不用调用stopSelf
• 提供onBind的默认实现,返回null
• 提供onStartCommand的默认实现,这个方法发送intent给工作序列,然后发送intent给onHandleIntent实现。
下面的实现:
所有需要的就是:
a constructor and an implementation of
onHandleIntent()
public class HelloIntentService extends IntentService { /** * A constructor is required, and must call the super IntentService(String)
* constructor with a name for the worker thread. */ public HelloIntentService() { super("HelloIntentService"); } /** * The IntentService calls this method from the default worker thread with * the intent that started the service. When this method returns, IntentService * stops the service, as appropriate. */ @Override protected void onHandleIntent(Intent intent) { // Normally we would do some work here, like download a file. // For our sample, we just sleep for 5 seconds. long endTime = System.currentTimeMillis() + 5*1000; while (System.currentTimeMillis() < endTime) { synchronized (this) { try { wait(endTime - System.currentTimeMillis()); } catch (Exception e) { } } } }}
这个IntentService的启动也很简单,不过sunshine中使用了一个BroadCastReceiver,然后使用这个广播启动service。
Intent alarmIntent = new Intent(getActivity(), SunShineService.AlarmReceiver.class);alarmIntent.putExtra(SunShineService.LOCATION_QUERY_EXTRA, location);PendingIntent pi = PendingIntent.getBroadcast(getActivity(), 0, alarmIntent, PendingIntent.FLAG_ONE_SHOT);AlarmManager am = (AlarmManager)getActivity().getSystemService(Context.ALARM_SERVICE);am.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + 5000, pi);
static public class AlarmReceiver extends BroadcastReceiver{ @Override public void onReceive(Context context, Intent intent) { Intent sendInentd = new Intent(context, SunShineService.class); String location = intent.getStringExtra(SunShineService.LOCATION_QUERY_EXTRA); sendInentd.putExtra(SunShineService.LOCATION_QUERY_EXTRA, location); context.startService(sendInentd); }}
有关service,我们还要学习service和通知组合使用的问题。下一个文章开始讲。通知和服务者两者还是有密切的关系的。
0 0
- 从网络获取数据(1)从newThread到AsyncTask在到IntentService
- 从网络里面获取数据写入到文件
- 从网络获取数据,并绑定到listview上
- 自制lenet:从获取数据到网络编写…
- 自制lenet:从获取数据到网络编写…
- AsyncTask从精通到放弃
- IntentService 从使用到源码分析
- IntentService 详解(从使用到源码撸一遍)
- 从网络获取图片加到view
- 从网络请求数据添加到数据库
- 从网络请求数据保存到数据库。
- Java网络编程从入门到精通(26):在服务端接收和发送数据
- Java网络编程从入门到精通(26):在服务端接收和发送数据
- 从页面获取取数据到数据库
- android 从 service 获取数据 到 activity
- 从IntentService到HandlerThread再到Looper、Handler、Message
- 数据从kafka到hive(1)
- 从网络获取数据
- 使用TraceView观察Windows PCIE驱动设备加载和卸载过程
- 浅谈四轴飞行器的力原理
- 用户体验的分类----产品经理深入浅出课程
- 用CSDN Markdown在线编辑器写博客
- MFC为控件添加消息响应函数(事件)
- 从网络获取数据(1)从newThread到AsyncTask在到IntentService
- linux中的crontab定时任务
- 比百度还好用的搜索功能,支持「多条件」搜索哟
- Learn Lua in 15 Minutes
- 黑客丛林之旅通关攻略
- 男子钓鱼傻眼了
- 【HDU】 2732 Leapin' Lizards
- opencv3.0.0 and ubuntu15.10:CMake Error at 3rdparty/ippicv/downloader.cmake:75
- STL---heap概述,make_heap,sort_heap,pop_heap,push_heap