安卓核心技术中级——Handle与多线程

本文详细介绍了Android中Handler机制的工作原理及应用,包括如何避免内存泄漏、实现闪屏页及使用AsyncTask进行异步任务处理等内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Handler简介

在Android开发中,我们常常使用单独的线程来完成某些操作,比如用一个线程来完成从网络上下载图片,然后显示在一个ImageView上,在多线程操作时,Android必须保证以下两点:
1、不要阻塞UI线程
2、不要再UI线程之外访问Android UI工具包

在两个线程中访问时使用handler

public class MainActivity extends AppCompatActivity {

    private TextView textView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textView = (TextView) findViewById(R.id.textView);
    }

    private Handler handler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what){
                case 100:
                    textView.setText("下载完成");
                    break;
            }
        }
    };

    public void downloadClick(View v){
        //使用线程模拟下载操作
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (true){
                    try {
                        Thread.sleep(3000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    break;
                }
//                下载完成后,更新UI状态
//                不可以在此访问textView,内部线程不可以访问UI线程
//                textView.setText("下载完成");

                //100存储到what中
                handler.sendEmptyMessage(100);
//                Message msg = handler.obtainMessage();//获取一个消息对象
//                msg.what = 100;
//                msg.obj = "要存储的信息";//任意类型都可以
//                handler.sendMessage(msg);//发送消息
            }
        }).start();
    }
}

在这里插入图片描述
在这里插入图片描述

Handler常用API

使用Handler可以完成以下两点工作:
1、消息调用和在将来的某个时间段执行一个Runnable
2、多个任务加入到一个队列中执行

//100存储到what中
 handler.sendEmptyMessage(100);//发送一个空消息,标记为100
 Message msg = handler.obtainMessage();//获取一个消息对象
 msg.what = 100;
 msg.obj = "要存储的信息";//任意类型都可以
 handler.sendMessage(msg);//发送消息
 handler.sendEmptyMessageAtTime(200,System.currentTimeMillis()+3000);//在指定时间后发送消息
 handler.sendEmptyMessageDelayed(300,2000);//延迟多少时间后发送消息

Handler内部实现原理

handle机制

  • 1、Message 消息对象,内部使用链表结果实现一个消息池,用于重复利用,避免大量创建消息对象,造成内存浪费
  • 2、Handler 消息处理者,通过该对象把消息存入消息队列,并最好通过handlerManager方法处理消息
  • 3、MessageQueue 消息队列,用于存储Message对象的数据结构,先进先出
  • 4、Looper 消息队列的处理者,用于循环检测消息队列,从消息队列中一个一个的取出消息对象,传入HandlerMessage方法

Android启动程序时会在UI线程中创建一个MessageQueue

Handler内存泄漏分析

错误代码:

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_handler_memorry);

        //使用handler延迟执行一个runnable(10分钟)
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                System.out.println("runnable");
            }
        },1000+60+10);
        finish();//关闭当前Activity
    }

    private Handler handler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
        }
    };

正确代码:

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_handler_memorry);

        //使用handler延迟执行一个runnable(10分钟)
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                System.out.println("runnable");
            }
        },1000+60+10);
        finish();//关闭当前Activity
    }

    private MyHandler handler = new MyHandler(this);

    //
    private static class MyHandler extends Handler{
        WeakReference<HandlerMemoryActivity> weakReference;
        public MyHandler(HandlerMemoryActivity activity){
            weakReference = new WeakReference<HandlerMemoryActivity>(activity);
        }
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            HandlerMemoryActivity activity = weakReference.get();
            if(activity!=null){
//                tv.setText();
            }

        }
    }

使用Handler实现APP的闪屏页

闪屏页的作用

  • 1、提供欢迎界面
  • 2、初始化工作

在清单文件中添加android:theme="@android:style/Theme.NoTitleBar.Fullscreen"

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_splash);

        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                startMainActivity();
            }
        },3000);
    }

    private void startMainActivity(){
        Intent intent = new Intent(this,MainActivity.class);
        startActivity(intent);
    }

    private Handler handler = new Handler();

在这里插入图片描述

AsyncTask

适用于简单的异步处理,不需要借助线程和Handler即可使用,AsyncTask是抽象类,定义了三种泛型类型:
*Params启动任务执行的输入参数,比如HTTP请求的URL
*Progress后台任务执行的百分比
*Result后台执行任务最终返回的结果,比如String

public class MainActivity2 extends AppCompatActivity {

    private TextView info;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);
        info = (TextView)findViewById(R.id.info);
    }

    public void asyncTaskClick(View v){
        new MyAsyncTask(this).execute();
    }

    /***
     * 通过一个AsyncTask实现一个异步任务
     * 第三个值是doInBackground的返回值类型
     */
    private static class MyAsyncTask extends AsyncTask<String,Integer,String>{

        private MainActivity2 activity;
        public MyAsyncTask(MainActivity2 activity){
            this.activity = activity;
        }

        //执行任务之前触发的事件方法,可以在该方法中作一些初始化工作
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            System.out.println("onPreExecute");
            activity.info.setText("开始执行任务。。。");
        }

        //执行后台任务的方法,类似于线程,所以不能在该方法中访问UI组件
        @Override
        protected String doInBackground(String... strings) {
            for(int i=0;i<10;i++){
                System.out.println(i);
                publishProgress(i);//更新进度
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            return "success";
        }

        //更新进度值
        @Override
        protected void onProgressUpdate(Integer... values) {
            super.onProgressUpdate(values);
            activity.info.setText("档期的值为"+values[0]);
        }

        //当doInBackground方法返回后被调用
        @Override
        protected void onPostExecute(String s) {
            super.onPostExecute(s);
            activity.info.setText(s);
        }
    }
}

在这里插入图片描述 在这里插入图片描述
AsyncTask-下载文件示例

public void downloadClick(View v){
        new DownloadAsyncTask(this).execute("");//图片下载地址
    }

    private static class DownloadAsyncTask extends AsyncTask<String,Integer,Integer>{

        private MainActivity2 activity;
        public DownloadAsyncTask(MainActivity2 activity){
            this.activity = activity;
        }

        //初始
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            activity.pb.setProgress(0);
        }

        @Override
        protected Integer doInBackground(String... strings) {
            String s = strings[0];
            try {
                URL url = new URL(s);
                //打开链接
                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                int size = conn.getContentLength();//获取文件大小
                //0表示需要更新的最大进度值,1表示更新档期下载的进度值
                publishProgress(0,size);
                byte[] bytes = new byte[20];
                int len = -1;
                InputStream in = conn.getInputStream();
                FileOutputStream out = new FileOutputStream("/sdcard/"+System.currentTimeMillis()+".jpg");//图片存储地址
                while ((len=in.read(bytes))!=-1){
                    out.write(bytes,0,len);
                    publishProgress(1,len);//更新进度
                    out.flush();
//                    Thread.sleep(500);
                }
                out.close();
                in.close();
            } catch (MalformedURLException e) {
                e.printStackTrace();
            }catch (IOException e){
                e.printStackTrace();
            }

            return 200;
        }

        @Override
        protected void onProgressUpdate(Integer... values) {
            super.onProgressUpdate(values);
            switch (values[0]){
                case 0:
                    activity.pb.setMax(values[1]);
                    break;
                case 1:
                    activity.pb.incrementProgressBy(values[1]);
                    break;
            }
        }

        @Override
        protected void onPostExecute(Integer integer) {
            super.onPostExecute(integer);
            if(integer == 200){
                activity.info.setText("下载完成");
            }
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值