从网络获取数据(1)从newThread到AsyncTask在到IntentService

概述

安卓不允许在UI线程中发送网络请求,因此必须新启动一个线程。

如果我们在活动中new Thread,这样就会有问题,这个线程会随着活动的生命周期结束而结束,如果活动的命比这个线程短,活动死掉了,线程还没有进行完,然后也不幸

挂了,这样,获取数据的任务就相当于是失败了,这肯定是不可以的啊。所以我们需要使用一个后台进程,比如AsyncTask,但是这个AsyncTask也要能快速完成(最多几秒),

不过他也有的一个问题就是,如果用户选择屏幕,后台的那个AsyncTask没有执行完,又会新建一个AsyncTask,这就导致资源的浪费了,不过应该问题不大,我们还是要知道

这个AsyncTask的。最后就是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);

}

在doInBackground中执行查询,然后解析json,批量插入插入数据库。

其实也挺简单的。

IntentService

这就是服务的使用了。安卓系统提供了两种实现,

直接继承Service:我们需要启动一个新线程来执行我们的操作,因为默认服务使用主线程,会影响活动的表现

继承IntentService:

使用一个工作线程处理请求,一次一个。

如果我们不需要同时处理多个请求,实现IntentService是一个好选择,只需要实现onHandleIntent()方法,传递一个Intent,就在后台工作了。

IntentService做了下面的事:

? 创建一个默认的工作线程执行所以传递给onStartCommand的intents独立于应用的主线程(新的线程了,所以不会干扰,那还说我自己要新启线程,应该是直接Service需要)

? 创建一个工作序列,一次传递一个intent给onHandleIntent实现,所以永远不用担心多线程

? 所有的开启请求被处理完之后停止服务,所以永远不用调用stopSelf

? 提供onBind的默认实现,返回null

? 提供onStartCommand的默认实现,这个方法发送intent给工作序列,然后发送intent给onHandleIntent实现。

下面的实现:

所有需要的就是:

a constructor and an implementation ofonHandleIntent()

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和通知组合使用的问题。下一个文章开始讲。通知和服务者两者还是有密切的关系的。

时间: 2024-08-29 05:53:05

从网络获取数据(1)从newThread到AsyncTask在到IntentService的相关文章

从网络获取数据,解析后输出。

我们要做的是从网络获取数据,在Activity中显示出来. 首先我们要导入gson包,它的作用是把Json字符串转换成相等的Java对象.把从网络获取数据和保存数据的方法写成类,方便以后调用. import java.io.BufferedReader; //从网络获取数据import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.net.HttpURLCon

网络获取数据的Xml的Pull解析

网络获取的XML的Pull解析 <?xml version="1.0" encoding="utf-8" ?> - <students> - <student xuehao="1233">  <name>张三</name>   <address>北京市昌平区</address> - <call>  <phone>010-37464567&l

iOS中从网络获取数据的几种方法的比较

IOS中获取网络数据一般有三种:1.NSURLCondition(已过时) 2.NSURLSession  3.三方库AFNetWorking NSURLSession 是苹果对NSULRCondition的替代品,NSURLSession比NSURLCondition多了 1.可配置的数据信息NSURLSessionConfiguration,NSURLSessionConfiguration使你可以设置你要请求的数据,通常的设置如缓存,也可以使用默认的配置信息defaultCongurati

从网络获取数据(2)使用SyncAdapter

之前我们讲的都是及时传输数据,这些随机的数据传输不利于管理,影响内存或者电池的使用,现在安卓提供了一个sync adapter框架, 帮助管理和自动进行数据传输,并且在不同app间合作进行同步.还有如下特色:  Plug-in architecture 允许我们添加数据传输的代码到系统以可调用组件的形式  Automated execution 允许我们基于一些标准的自动数据传输,包括数据改变.逝去时间或者一天中的时间(including data changes, elapsed time

AFN 获取数据,数据解析:JSON 介绍

AFN的介绍: 可以自动对服务器返回的数据进行解析,默认将服务器返回的数据当做 JSON 数据解析 是集XML解析,Json解析,网络图片下载,plist解析,数据流请求操作,上传,下载,缓存等网络众多功能于一身的强大的类库. 网络获取数据一直是手机软件的重中之重,如果处理的不好,会造成很差的用户体验.随着ASIHTTPRequest的停止更新,更换网络库是必然的事情,AFNetworking就是很好的替代品.而且都是轻量级,不要担心加入太多库会多软件性能有影响. AFN使用的注意事项:  (1

Android网络之数据解析----使用Google Gson解析Json数据

[声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/4063452.html 联系方式:[email protected] [正文] 文章回顾: Android网络之数据解析----SAX方式解析XML数据 一.Json数据的介绍                                                             

基于Android4.0ListView从网络获取图片文字资源显示

平时的一些Android学习视频中,他们都是基于Android的去使用ListView,我看到都是会在UI线程中去访问网络获取数据,但是这在Android4.0之后是行不通的. 首先我们来理一下思绪: 我们需要从网络上下载一份xml数据,里面包含了需要显示的文字和图片路径.所以我们首先需要的就是先去下载数据,下载数据完成之后再在Adapter中显示图片的时候去下载图片,然后显示出来.这是基本的思路.但是做着做着会发现一些问题,比如,我们如何能保证数据下载完全,才去绑定适配器和数据他们.然后假如我

volley源码解析(四)--CacheDispatcher从缓存中获取数据

从上一篇文章我们已经知道,现在要处理的问题就是CacheDispatcher和NetworkDispatcher怎么分别去缓存和网络获取数据的问题,这两个问题我分开来讲. 但是首先说明的是,这两个问题其实是有联系的,当CacheDispatcher获取不到缓存的时候,会将request放入网络请求队列,从而让NetworkDispatcher去处理它: 而当NetworkDispatcher获得数据以后,又会将数据缓存,下次CacheDispatcher就可以从缓存中获得数据了. 这篇文章,就让

获取数据源数据的实现---Architecting Android

UserRepository,这个接口,描述了Repository提供给用户的功能就是getUsers,getUser(ID).用户只管使用,其它细节无需理会. /** * Interface that represents a Repository for getting {@link User} related data. */ public interface UserRepository { /** * Get an {@link rx.Observable} which will em