现在的位置: 首页 > 综合 > 正文

ArrayList和数组之间的一些转换 Handler的主线程与子线程通信 内部类的使用

2012年11月24日 ⁄ 综合 ⁄ 共 3720字 ⁄ 字号 评论关闭

1. ArrayList和数组之间的一些转换

ArrayLlist底层就是用数组实现的,并且提供了两个方法给我们来将集合转换成数组

1. public Object[] toArray() 这个数组中存储的是object对象
2. public <T> T[] toArray(T[] a) 这个数组中存储的是指定的T类型的对象
说说使用这两个方法可能会出现的问题
使用第一个方法经常会出现类型转换的问题
代码:
ArrayList<String> list = new ArrayList<String>();
String[] whereArgs = (String[]) list.toArray();
就会抛出类转换异常。这样转换时不对的,这里涉及到了泛型的强转问题,晚上看看再补充。
 
第二个方法:
代码:
ArrayList<String> list = new ArrayList<String>();

String[] whereArgs = new String[list.size()];

whereArgs = list.toArray(whereArgs);

这样写是ok的,但是如果创建数组对象时,没有指定数组的大小,就会报错

这个方法中的参数a相当于c语言中的传入性参数,将一个空数组传给集合,集合将其填满,再返回。

 

 

2. 使用Handler进行子线程与主线程之间的通信

从一个错误开始:

public class HomeActivity extends Activity {
    private static final String tag = "HomeActivity";
    private Button mStart_btn;
    private Thread mSubThread;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
      
        mStart_btn = (Button) this.findViewById(R.id.btn);
        Log.i(tag, "mainThread: "+Thread.currentThread().getId());
        mStart_btn.setOnClickListener(new View.OnClickListener() {
           
            @Override
            public void onClick(View v) {
                mSubThread = new Thread(new Runnable() {
                    @Override
                    public void run() {
                        Log.i(tag, "subThread: "+Thread.currentThread().getId());
                        Looper mainLooper = Looper.getMainLooper();
                        Handler subHandler = new Handler(mainLooper);
                        Message mes = subHandler.obtainMessage(1,1,1);
                       
                        subHandler.sendMessage(mes);//向主线程发送数据
                   
                    }
                });
                mSubThread.start();
           
            }
        });
    }
    private Handler mhandler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            Log.i(tag, "handler01 is working");
            mSubThread.stop();
           
        }
       
    };

 

结果:并没有打印出“handler01 is working”,为什么?

在子线程中创建Handler对象,并且绑定主线程的Looper,按理说应该可以进行子线程与主线程之间的通信了,但是为什么会出现上述情况呢,这要从Handler的源码说起

public final boolean sendMessage(Message msg)
   {
       return sendMessageDelayed(msg, 0);
   }

public final boolean sendMessageDelayed(Message msg, long delayMillis)
   {
       if (delayMillis < 0) {
           delayMillis = 0;
       }
       return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
   }

public boolean sendMessageAtTime(Message msg, long uptimeMillis)
   {
       boolean sent = false;
       MessageQueue queue = mQueue;
       if (queue != null) {
          msg.target = this;//将这个消息的处理handler设为自己
           sent = queue.enqueueMessage(msg, uptimeMillis);
       }
       else {
           RuntimeException e = new RuntimeException(
               this + " sendMessageAtTime() called with no mQueue");
           Log.w("Looper", e.getMessage(), e);
       }
       return sent;
   }
我在子线程中直接使用的Handler类创建的对象,Handler类handleMessage方法是空的,他没有任何处理,所以不会打印任何东西。

 

总结:

通过这个错误纠正了我以前对Handler理解的一个误区,我以前人为在子线程中创建Handler对象,并且绑定主线程的Looper,这样就可以将消息发送到主线程维护的队列中,然后主线程就会将这个消息交给主线程的Handler进行处理,当有多个Handler绑定同一个线程的时候,就是那个Handler合适就交给谁处理,其实不是这样的饿,子线程中的Handler对象,在绑定了主线程的Looper之后,它就属于主线程了,并且他自己的消息自己处理。这里又有个问题,比如说上述代码中,当run方法执行完之后,Handler对象的引用就被销毁了,那么Handler对象销毁了吗,没有销毁,这就是上述红色代码的作用。给这个对象重新建立一个引用。我想这应该是一种设计模式,我还有待研究。还有一个问题,我们用Handler来更新activity的ui显示,当要更改的activity被销毁了,或者是处于不可见状态,系统又是怎么处理的呢?Looper轮询出这则消息,然后通过msg.target.dispatchMessage(msg);交给Handler处理,Handler就回去调用handleMessage方法,执行方法体饿时候,各种对象都不存在了,也就不执行了。(这仅是主观想象,还有待研究)。

 

3. android错误 Conversion to Dalvik format failed with error 1

解决办法:

Project > Clean... > Clean project selected below > Ok

 

4. 内部类的使用

    4.1 什么情况下使用内部类?

          当你在类A中需要用到类B的对象,并且在类B中的方法里还要访问类A的成员变量和方法,这个时候,你就需要将类B写成类A的内部类了。

    4.2 外部如何引用内部类

          1. 用关键字static修饰内部类,那么这个内部类就相当于外部类,但是这种用法很少见,有很大的局限性,例如内部类不能访问外部类中非static的成员

          2. 通过创建对象从外部引用,先要创建外部类对象,然后通过外部类对象去new内部类的实例,实际上就是将内部类看成外部类的一个成员属性而已。

抱歉!评论已关闭.