android 获取数据-需要注意的地方(系统优化)

来源:互联网 发布:大数据精准营销特点 编辑:程序博客网 时间:2024/05/17 05:13

应该避免的操作

在主线程上应该避免下列操作:
1 与网络相关的操作
2 需要对文件系统进行读写操作的任务
3 任何种类的繁重事务处理(如图片或视频修改)
4 在等待某件事务完成时会阻碍线程执行的任务

这个列表几乎包含了大多数情况,所以,作为一般规律,如果不涉及对用户界面的设置或修改,就不要在主线程上操作。

什么时候在主线程上

无论何时,当一个方法被系统调用时,(除非显式声明其他调用者) 就可以确保是位于主线程上。再次强调,作为一般规律,如果用户不在自己创建的进程内,就基本可以假定是在主线程上,那就要当心了。

举个例子,下载一个图片,因为会与网络交互,所以要独立到一个service里。不能独立在一个线程里,设置图片的任务也就是更改主进程的UI只能在主进程中更新。
所以下面的方法是错误的。

public void onCreate(){new Thread(){    public void run()    {    try{        URL url = new URL("http://baidu.com");        HttpURLConnection httpCon = (HttpURLConnection)url.openConnection();        if(httpCon.getResponseCode() != 200) throw new Exception("Failed to connect");        InputStream is = httpCon.getInputStream();        Bitmap bt = BitmapFactory.decodeStream(is);        ImageView iv = (ImageView)findViewById(R.id.remote_image);        iv.setImageBitmap(bt);    }        catch(Exception e){        }      }    }.start();}

出现这个问题,主线程是唯一一个具有改变用户界面权限的线程,调用setImageBitmap就完全属于这样的改变,因此只能在主线程上才能完成。

所以,需要回到主线程

android系统通过活动类提供了一种方式,只要能够访问活动就可以回到主线程,下面来修改上面的代码。

public void onCreate(){new Thread(){    public void run()    {    try{        URL url = new URL("http://baidu.com");        HttpURLConnection httpCon = (HttpURLConnection)url.openConnection();        if(httpCon.getResponseCode() != 200) throw new Exception("Failed to connect");        InputStream is = httpCon.getInputStream();        Bitmap bt = BitmapFactory.decodeStream(is);        ImageActivity.this.runOnUiThread(new Runnable(){        public void run()        {            ImageView iv = (ImageView)findViewById(R.id.remote_image);            iv.setImageBitmap(bt);        }   });    }        catch(Exception e){        }      }    }.start();}

记住,现在已经运行在一个线程中,所以需要用this指针会指向线程自身,需要调用runOnUiThread方法。

更好的办法

AsyncTask

AsyncTask介绍

AsyncTask是一个扩展的抽象类,为一个耗时的异步任务提供基本的框架。

Android的AsyncTask比Handler更轻量级一些,适用于简单的异步处理。
首先明确Android之所以有Handler和AsyncTask,都是为了不阻塞主线程(UI线程),且UI的更新只能在主线程中完成,因此异步处理是不可避免的。

Android为了降低这个开发难度,提供了AsyncTask。AsyncTask就是一个封装过的后台任务类,顾名思义就是异步任务。

AsyncTask直接继承于Object类,位置为android.os.AsyncTask。要使用AsyncTask工作我们要提供三个泛型参数,并重载几个方法(至少重载一个)。
三种泛型类型分别代表“启动任务执行的输入参数”、“后台任务执行的进度”、“后台计算结果的类型”。在特定场合下,并不是所有类型都被使用,如果没有被使用,可以用java.lang.Void类型代替。

有两个方法是必须要实现的。doInBackground和onPostExecute(Result)这两个方法。

onPreExecute() /*这里是最终用户调用Excute时的接口,当任务执行之前开始调用此方法,可以在这里显示进度对话框。*/doInBackground(Params…) /*后台执行,比较耗时的操作都可以放在这里。注意这里不能直接操作UI。此方法在后台线程执行,完成任务的主要工作,通常需要较长的时间。在执行过程中可以调用publicProgress(Progress…)来更新任务的进度。*/onPostExecute(Result)  /*相当于Handler 处理UI的方式,在这里面可以使用在doInBackground 得到的结果处理操作UI。 此方法在主线程执行,任务执行的结果作为此方法的参数返回*/

这项技术的缺点:

http://www.oschina.net/question/54100_27825

IntentService

这是个出色的方法,移动大量的数据而不依赖于任何特定的活动甚至应用,AsyncTask总会占用主线程至少两次, 调用preexecute和postexecute方法,而且它总是必须属于一个能够显示在屏幕上的活动,IntentService没有这样的限制。
流程:
首先声明服务
按照下载图片作为例子,

0 0
原创粉丝点击