FrameWork之开篇基础

 

    今天的工作情况如下:

     1)上午修改项目的小bug,主要是在处理之前业务中没有考虑到的情况,如服务器崩溃、客户系统异常等造成的程序异常导致的数组null和越界等异常,只加了一个核心判断代码:

         

if(tempList != null){
            //复制数字,同时指定长度
            ret.specialMesList = Arrays.copyOf(tempList, ret.specialMesList.length);
            //遍历是否有null值存在,自动补齐
            for(int i =0;i<ret.specialMesList.length;i++){
                if(ret.specialMesList[i] == null){
                    ret.specialMesList[i] = "0";
                }
            }
            //。。tempList在static方法里,需手动设为null,清除之
            tempList = null;
        }

    2)关于异步消息处理线程。

          之所以要在这里说下这个,是因为昨天晚上正准备睡觉的时候看到群里有位兄弟提出的一个问题,他的代码大概如下:

new Thread(new Runnable(){
			@Override
			public void run(){
				try {
					Thread.sleep(2000);
					//准备一个MessageQueue队列
					Looper.prepare();
					//子线程中对ui界面进行操作会出问题
					Handler handler = new Handler(){
						@Override
						public void handleMessage(Message msg){
							switch(msg.what){
							case 0: 
								Toast.makeText(mContext, "哈哈",Toast.LENGTH_LONG).show();
								text_view.setText("界面被改变了");
								text_view.invalidate();
								break;
							}
						}
					};
					//取得Message对象
					Message msg = handler.obtainMessage();
					//这里发送的消息实际上发送到子线程的消息队列了,UI线程并没有接收到消息
					msg.what = 0;
					handler.sendMessage(msg);
					
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				
			}
		}).start();
      问题描述:首先在主线程中开启一个子线程并start,然后在子线程的run中执行界面更新操作,为什么会没有更新了呢?运行不会出错也没有异常,就是没有预期的效果。原因在于Android的异步线程的处理原理上。
     实际上上面的代码所在的APK程序中主线程有一个MessageQuese(消息队列),子线程也有一个MessageQuese,子线程将消息发送到他自己的消息队列中了,并没有发送到主线程,也就是说子线程并没有和主线程有通信交流。更深层次的说明需要解决如下问题:

      ① 什么是异步消息处理线程?

          对于普通的线程而言,执行完run方法内的代码后现场就结束了。但是异步消息处理线程是指当线程启动后悔进入一个无线循环体之内,每循环一次就从其内部的消息队列中取出一条消息,并回调想要的消息处理函数,执行完之后就亟需循环读取处理消息,如果消息为空线程就会等待,知道消息队列中有新的消息因此异步消息处理线程有一个典型的特征就是必须具备一个且仅有一个消息队列即MessageQuese。

      ② 什么情况下会使用异步消息处理线程呢?有两个地方:

           第一就是任务需要常驻,比如处理用户交互的任务。

           第二任务需要根据外部传递的消息作不同的操作。

           在Android中,由于程序需要经常接收用户的输入消息来更新界面,程序会把这个接收用户消息和如何处理交给了主线程(即UI线程)来完成,由于此任务是需要常驻的,所以主线程是一个异步消息处理线程,也因为主线程常驻而且是不安全的,所谓主线程不安全就是如果一个程序中有很多个子线程对界面进行修改更新,这些更新消息都交给UI线程来处理,那么问题来了,万一子线程都对同一个界面对象(可能说的不规范)进行操作,UI线程该如何反应?而这也就有可能会阻塞(线程阻塞是指线程间的互相等待,有可能会一直等下去)主线程的行为,Android中的UI线程阻塞即使指当多个子线程同时要求对同一对象界面进行操作修改等问题时,主线程有可能会被子线程之间阻塞(语言不规范 - -、)。

          上面所说的子线程并非是异步消息处理线程,因为如果是子线程是异步消息处理线程那么他就无法向UI线程发送消息了,他就会将消息发送到自己的MessageQueue。下同。

          所以,从上面的描述可以知道,虽然我们知道了什么时候使用异步消息处理线程,但是我们应该知道如何避免阻塞UI线程。Android为了避免此问题,已经明确了程序中的所有非UI线程不能出现有对UI进行操作的业务逻辑。这就是Android中的单线程模式。

          在单线程模式下,所以子线程需要更新界面的操作都需要报告UI线程,由UI线程来进行处理。所有关于界面更新的操作都由UI线程包办的,子线程只负责发送需要更新哪个界面的请求,如此就可以避免子线程间的冲突。

          ③  子线程该如何和UI线程通信以便通知UI线程更新界面?

           Android提供了Handler机制让子线程和UI线程进行通信。

           通过Looper、Message来实现。Looper是继承自Thread的。我们在使用时Handler对象必须在主线程中创建,因为,在主线程中的Handler才属于主线程的,这样才可以将消息发送给主线程。主线程中可以直接创建使用Handler,而不必要调用Looper.prepare()创建MessageQueue也不用调用Looper.loop()进入循环,因为主线程在创建时已经创建好了都,直接使用Handler来分发消息即可。

         Handler在应用中除了可以用来接收子线程发送的数据外还可以作为一个业务处理逻辑的中间组件,通过Message来传递完成不同的操作。




  

你可能感兴趣的:(FrameWork之开篇基础)