Android杂谈

Android杂谈

本文章用自己的复习巩固,文章中的内容都是通过Android疯狂讲义整理

1.事件监听

三种对象:

  • Event Source(事件源):发生事件的来源,一般的情况就是各个控件,比如:textview,button
  • Event (事件):封裝了事件源上发生的特定的事情,比如textview按下激发onKeyDown()
  • eventlistener(事件监听器):监听事件源发生的事件,并且对事件发生相应,比如按下textview时做一个跳转等

2.Configuration简介

在Activity中获取系统的Configuration对象:

Configuration con=getResources().getConfiguration();

Configurationde的属性 :

  • public float fontScale:获取当前用户设置的字体的缩放因子
  • public int keyboard:设备键盘的类型。KEYBOARD_NOKEYS,KEYBOARD_QWERTY(普通电脑键盘),KEYBOARD_12KEY(只有12键的小键盘).
  • public int keyboardHidden:判断当前键盘是否可用。
  • public Locale locale:获取当前用户的场所。
  • public int mcc:获取移动信号的国家码。
  • public int mnc:获取移动信号的网络码。
  • public int navigation:判断方向导航设备的类型
  • public int orientation:判断屏幕的横竖屏。
  • public int touchscreen:获取系统触摸屏的方式。
  • public int keyboardHidden:判断当前键盘是否可用。

重写onConfigurationChanged方法,可以监听系统设置的更改,常用的情况就是监听横竖屏的切换,从而进行相应的处理。

3.Handler,Looper,MessageQueue的关系

  • Handler:用于消息的发送和接受,程序使用Handler发送消息,被Handler发送的消息必须被送到指定的MessageQueue。所以如果要Handler正常的使用,就需要在该线程中有一个指定的MessageQueue。而通过下面的代码可以看出MessageQueue是由Looper的构造函数创建的,所以如果希望Handler能够正常的发送和接受消息,就必须在当前的线程中有一个Looper对象。
  • Message:handler接受和处理的消息对象
  • Looper:每一个线程只能有一个looper,如果有第二个会报错。他的loop方法负责读取MessageQueue中的消息,读到的消息发送给该消息的handler进行处理
  • MessageQueue:消息队列,他采用先进先出的方式管理Message,程序创建Looper对象的时候,会在Looper的构造函数中创建MessageQueue对象。
 private Looper(boolean quitAllowed) {
    mQueue = new MessageQueue(quitAllowed);
    mThread = Thread.currentThread();
}

Looper得构造方法是私有的不能外部访问,所有looper的创建不是通过外部new方法创建。

 /** Initialize the current thread as a looper.
  * This gives you a chance to create handlers that then reference
  * this looper, before actually starting the loop. Be sure to call
  * {@link #loop()} after calling this method, and end it by calling
  * {@link #quit()}.
    翻译这段注释:实例化当前线程创建一个looper对象。
    让你在循环这个loop之前有机会创建handlers,然后引用这个looper对象。在你确定引用这个方法之后你必须调用方法loop(),同时最后会调用quit()方法。
  */

public static void prepare() {
    prepare(true);
}

private static void prepare(boolean quitAllowed) {
    //判断当前线程是否有looper对象,如果有就报错
    if (sThreadLocal.get() != null) {
        throw new RuntimeException("Only one Looper may be created per thread");
    }
    sThreadLocal.set(new Looper(quitAllowed));
}


/**
 * Run the message queue in this thread. Be sure to call
 * {@link #quit()} to end the loop.
 */
public static void loop() {
    //判断looper对象是否创建成功,如果没有会抛出异常
    final Looper me = myLooper();
    if (me == null) {
        throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
    }
    final MessageQueue queue = me.mQueue;

    // Make sure the identity of this thread is that of the local process,
    // and keep track of what that identity token actually is.
    Binder.clearCallingIdentity();
    final long ident = Binder.clearCallingIdentity();

    for (;;) {
        Message msg = queue.next(); // might block 获取消息队列的下一个消息,如果没有就会阻塞在这里
        if (msg == null) {
            // No message indicates that the message queue is quitting.
            //如果为空 表示消息队列正在退出
            return;
        }

        // This must be in a local variable, in case a UI event sets the logger
        final Printer logging = me.mLogging;
        if (logging != null) {
            logging.println(">>>>> Dispatching to " + msg.target + " " +
                    msg.callback + ": " + msg.what);
        }

        final long traceTag = me.mTraceTag;
        if (traceTag != 0 && Trace.isTagEnabled(traceTag)) {
            Trace.traceBegin(traceTag, msg.target.getTraceName(msg));
        }
        try {
            msg.target.dispatchMessage(msg);
        } finally {
            if (traceTag != 0) {
                Trace.traceEnd(traceTag);
            }
        }

        if (logging != null) {
            logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
        }

        // Make sure that during the course of dispatching the
        // identity of the thread wasn't corrupted.
        //确保在使用的过程中,线程的标识不会被损坏
        final long newIdent = Binder.clearCallingIdentity();
        if (ident != newIdent) {
            Log.wtf(TAG, "Thread identity changed from 0x"
                    + Long.toHexString(ident) + " to 0x"
                    + Long.toHexString(newIdent) + " while dispatching to "
                    + msg.target.getClass().getName() + " "
                    + msg.callback + " what=" + msg.what);
        }

        msg.recycleUnchecked();
    }
}

通过上面的代码,可以总结出:每一个线程只能有一个Looper对象,通过他来管理MessageQueue,他会不断的从消息队列中获取消息,并将消息分给对应的handler;而MessageQueue则是通过先进先出的方式管理Message;最后Handler则是把消息发送给Looper管理的MessageQueue,并处理looper发送给他的消息。

我们要注意的是:Handler分两种:

  • 主线程的Handler:也就是UI线程,在UI线程创建的时候,已经初始化了一个Looper对象,所有我们不需要在创建一个Looper对象,而是直接创建Handler就可以发送和接受消息
  • 子线程的Handler:我们需要手动创建一个Looper对象,并启动他。

下面是子线程调用的示例代码:

public  class MainActivity extends AppCompatActivity {

class  MyThread extends  Thread
{
    public Handler handler;
    @Override
    public void run() {
        super.run();
        //创建一个Looper对象
        Looper.prepare();
        //创建一个Handler对象在这里接受并处理消息
        handler=new Handler(){
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
            if(msg.what==0)
            {
                Toast.makeText(MainActivity.this,"测试是否有用!",Toast.LENGTH_LONG).show();
            }
            }
        };
        //启动这个Looper中消息队列的循环机制
        Looper.loop();
    }
}
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Button button= (Button) findViewById(R.id.button);
    final  MyThread thread=new MyThread();
    thread.start();
    button.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Message message= new Message();
            message.what=0;
            message.obj=10;
            //调用子线程中的handler对象发送消息
            thread.handler.sendMessage(message);
        }
    });
   }
 }
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值