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内部类的实例,实际上就是将内部类看成外部类的一个成员属性而已。