• 线程方法Android:异步调用详解


    PS:今天上午,非常郁闷,有很多简单基础的问题搞得我有些迷茫,哎,代码几天不写就忘。目前又不当COO,还是得用心记代码哦!

        在现实应用中经常会碰到比较耗时任务的处理,比如网络连接,数据库操作等情况时,如果这些操作都是放在主线程(UI线程)中,则会形成UI的假死景象,Android中可以应用AsyncTask和Handler两种异步方式来解决这类问题。

        AsyncTask:

        android提供的轻量级的异步类,可以直接继承AsyncTask,在类中实现异步操作,并提供接口反馈当前异步执行的水平(可以通过接口实现UI进度更新),最后反馈执行的结果给UI主线程.
    应用的长处:
    简单,快捷,进程可控
    应用的缺点:
    在应用多个异步操作和并须要进行Ui变革时,就变得复杂起来.

        在应用AsyncTask时处理类须要继承AsyncTask,提供三个泛型参数,并且重载AsyncTask的四个方法(至少重载一个)。

        三个泛型参数:
    1.Param 任务执行器须要的数据类型
    2.Progress 后台盘算中应用的进度单位数据类型
    3.Result 后台盘算返回结果的数据类型
    在设置参数时通常是这样的:String... params,这表示方法可以有0个或多个此类型参数;有时参数可以设置为不应用,用Void...便可。

        四个方法:
    1.onPreExecute() 执行预处理,它运行于UI线程,可以为后台任务做一些准备工作,比如绘制一个进度条控件。
    2.doInBackground(Params...) 后台进程执行的具体盘算在这里实现,doInBackground(Params...)是AsyncTask的症结,此方法必须重载。在这个方法内可以应用publishProgress(Progress...)改变当前的进度值。
    3.onProgressUpdate(Progress...) 运行于UI线程。如果在doInBackground(Params...) 中应用了publishProgress(Progress...),就会触发这个方法。在这里可以对进度条控件根据进度值做出具体的响应。
    4.onPostExecute(Result) 运行于UI线程,可以对后台任务的结果做出处理,结果就是doInBackground(Params...)的返回值。此方法也要经常重载,如果Result为null表明后台任务没有完成(被取消或者出现异常)。

        异步任务类代码:

        

    // AsyncTask异步方式下载图片
    class DownImageTask extends AsyncTask<String, Integer, Bitmap> {
    	// 执行预处理
    	@Override
    	protected void onPreExecute() {
    		super.onPreExecute();
    		// 显示进度条
    		progressBar.setVisibility(View.VISIBLE);
    		progressBar.setMax(100);
    	}
    	// 后台进程的执行
    	@Override
    	protected Bitmap doInBackground(String... params) {
    		try {
    			URL url = new URL(params[0]);
    			HttpURLConnection conn = (HttpURLConnection) url
    					.openConnection();
    			InputStream inputStream = conn.getInputStream();
    			bitmap = BitmapFactory.decodeStream(inputStream);
    			// 进度条的更新,我这边只是用一个循环来树模,在现实应用中要应用已下载文件的大小和文件总大小的比例来更新
    			for (int i = 1; i <= 10; i++) {
    				publishProgress(i * 10);
    				Thread.sleep(200);
    			}
    			inputStream.close();
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    		return bitmap;
    	}
    	// 运行于UI线程,对后台任务的结果做出处理,doInBackground方法执行的结果作为此方法的参数
    	@Override
    	protected void onPostExecute(Bitmap result) {
    		super.onPostExecute(result);
    		ImageView imageView = (ImageView) findViewById(R.id.image);
    		imageView.setImageBitmap(result);
    		progressBar.setVisibility(View.GONE);
    	}
    	// 运行于UI线程,如果在doInBackground(Params...)中应用了publishProgress(Progress...),就会触发此方法
    	@Override
    	protected void onProgressUpdate(Integer... values) {
    		super.onProgressUpdate(values);
    		progressBar.setProgress(values[0]);
    	}
    }
        每日一道理
    即使青春是一枝娇艳的花,但我明白,一枝独放永远不是春天,春天该是万紫千红的世界。 即使青春是一株大地伟岸的树,但我明白,一株独秀永远不是挺拔,成行成排的林木,才是遮风挡沙的绿色长城。即使青春是一叶大海孤高的帆,但我明白,一叶孤帆很难远航,千帆竞发才是大海的壮观。

        调用代码:

    public class MainActivity extends Activity {  
        private Button button;
        private ProgressBar progressBar; 
          
        @Override  
        public void onCreate(Bundle savedInstanceState) {  
            super.onCreate(savedInstanceState);  
            setContentView(R.layout.main);  
              
            button = (Button)findViewById(R.id.button);
            progressBar = (ProgressBar)findViewById(R.id.progressBar);
              
            button.setOnClickListener(new OnClickListener() {  
                  
                @Override  
                public void onClick(View v) {  
                    ProgressBarAsyncTask asyncTask = new DownImageTask();  
                    asyncTask.execute("http://www.baidu.com/img/baidu_jgylogo3.gif");
                }  
            });
        }

        

        Handler:

        

        Handler可以分发Message对象和Runnable对象到主线程中, 每个Handler实例,都市绑定到创建他的线程中(一般是位于主线程中)

        两个作用: 

        布置消息或Runnable 在某个主线程中某个地方执行

        布置一个动作在不同的线程中执行

        Handler平分发消息的方法:
    post(Runnable)
    postAtTime(Runnable,long)
    postDelayed(Runnable,long)
    sendEmptyMessage(int)
    sendMessage(Message)
    sendMessageAtTime(Message,long)
    sendMessageDelayed(Message,long)
    *以上post扫尾的方法在主线程中调用。
    *以上send扫尾的方法在其它线程中调用。

        示例代码:

    public class HandlerTestActivity extends Activity {
    
        private Button start;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            // TODO Auto-generated method stub 
            super.onCreate(savedInstanceState);
            setContentView(R.layout.handlertest);
            start = (Button) findViewById(R.id.start);
            start.setOnClickListener(new startListener());
    
            System.out.println("Activity Thread:" + Thread.currentThread().getId());
        }
    
        Handler  handler = new Handler(){
    
            @Override
            public void handleMessage(Message msg) {
                // TODO Auto-generated method stub
                if (msg.what == 1) {
                    //胜利,做一些操作
                } else {
                    //失败,..
                }
            }
            
        };
        Runnable thread  = new Runnable() {
    
                             @Override
                             public void run() {
                                 // TODO Auto-generated method stub 
                                 System.out.println("HandlerThread:" + Thread.currentThread().getId());
                                 //Message message = new Message();
                                 //message.what = 1;
                                 //handler.sendMessage(message);
    
                             }
                         };
    
        class startListener implements OnClickListener {
    
            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub 
                handler.post(thread);
                //Thread t = new Thread(thread);
                //t.start();
            }
        }
    
    }

        这个程序看上去仿佛实现了Handler的异步机制, handler.post(thread)仿佛实现了新启线程的作用,不过通过执行我们发明,两个线程的ID相同!也就是说,现实上thread还是本来 的主线程,由此可见,handler.post()方法并未真正新建线程,只是在原线程上执行而已,我们并未实现异步机制。将startListener改写成如下代码就能够实现异步:

        

    class startListener implements OnClickListener {
    
            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub 
                //handler.post(thread);
                Thread t = new Thread(thread);
                t.start();
            }
        }

        将runnable放到新创建的线程中执行,这样就实现了异步调用,如果须要在调用完成后通知或修改主线程,须要在Runnable类的run方法中调用handler.sendMessage(message)

        

    @Override
     public void run() {
         // TODO Auto-generated method stub 
         System.out.println("HandlerThread:" + Thread.currentThread().getId());
         Message message = new Message();
         message.what = 1;
         handler.sendMessage(message);
    }

    文章结束给大家分享下程序员的一些笑话语录: 人脑与电脑的相同点和不同点,人脑会记忆数字,电脑也会记忆数字;人脑会记忆程序,电脑也会记忆程序,但是人脑具有感知能力,这种能力电脑无法模仿,人的记忆会影响到人做任何事情,但是电脑只有程序软件。比尔还表示,人脑与电脑之间最重要的一个差别就是潜意识。对于人脑存储记忆的特别之处,比尔表示,人脑并不大,但是人脑重要的功能是联络,人脑会把同样的记忆存储在不同的地方,因此记忆读取的速度就不相同,而这种速度取决于使用的频率和知识的重要性。人脑的记忆存储能力会随着年龄增长而退化,同时记忆的质量也会随着年龄退化。经典语录网

  • 相关阅读:
    具体讲解有关“DB2“数据库的一些小材干1
    适用手段 Ubuntu Linux 8.04设置与优化2
    如何管理DB2数据库代码页不兼容的成效
    具体解说有关“DB2“数据库的一些小本领3
    深化分析DB2数据库运用体系的性能优化3
    实例讲解如安在DB2 UDB中正确的监控弃世锁2
    阅历总结:运用IBM DB2数据库的详细事变
    实例讲授如何在DB2 UDB中正确的监控死锁3
    DB2数据库在AIX上若何卸载并重新安顿
    轻松处置DB2创设存储历程时碰着的错误
  • 原文地址:https://www.cnblogs.com/xinyuyuanm/p/3091851.html
Copyright © 2020-2023  润新知