include与merge
参考http://fengweipeng1208.blog.163.com/blog/static/21277318020138229754135/
include
在写布局时,如果布局相同,可以将相同的布局提取出来单独成一个布局文件,然后在需要的地方通过<include>标签中的layout属性引入即可。
有两点需要注意:基于当前设备配置,引入的布局一样会经过筛选,适配;在<include>标签上指定android:id以及任何以android:layout_*开头的属性,可以覆盖引入的布局中根元素对应的属性,但这有一个前提:必须重写android:layout_height及android:layout_width(重写一个也不行),不然别的layout_*属性不会生效。
具体效果如下:
其中左边是直接引用和只重写一个layout_width或者layout_height时的样子;右边重写两个属性。
基于<include/>的这种特性可以使用<include/>进行适配。如果布局中有一部分需要根据屏幕方向进行更改,可以将该部分抽成独立的布局,并且通过<include/>进行引用,那么适配时只需要重写该独立布局,而对于引用该布局的布局却不需要进行更改。
merge
merge标签经常与include一起工作,主要用作代替实际组件,它可作为引入布局的根元素。布局中引入了另外一个以merge为根元素的布局时,merge的子元素也会直接被引入,结果它们成了<include>元素的父元素的子元素,而merge标签会被直接丢弃。merge天生是要被丢弃掉的,它只是用来满足xml文件的格式规范要求的:XML布局文件必须具有一个根元素。
如上图,如果引入的布局以LinearLayout(或者其它的ViewGroup),整个布局的直接子元素是2个,而如果换成merge则是3个。
merge相当于直接把<merge>的子元素复制到<include>父元素下,而不使用<merge>相当于直接把整个布局文件直接复制到<include>的父元素下(有可能会改变根元素的一些layout_*属性)。
之所以使用<merge>是为了减少布局的嵌套,提高UI效率。
非UI线程更新UI
参考:http://www.eoeandroid.com/thread-288638-1-1.html中的2楼。
android中不能在子线程中更新UI。但是下面一段代码却不会报错:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv = (TextView) findViewById(R.id.tv);
new Thread() {
public void run() {
Looper.prepare();
// 此时handler处于子线程中
Handler subHandler = new Handler() {
public void handleMessage(Message msg) {
System.out.println("线程:"
+ Thread.currentThread().getName());
tv.setText("我是在run中运行的");
};
};
subHandler.sendEmptyMessage(0);
Looper.loop();
};
}.start();
}
它的输出结果是:“线程:Thread-350”,这也证明了handleMessage()是执行在子线程中。但是如果我们发送消息之前调用Thread.sleep(2000),也就是让子线程睡一会,程序就会崩掉,原因就是:子线程修改了UI。因此可以推测:其实并不是能直接更新,而是某种检查机制还没起作用 (或者说晚于你的更新 )。
PendingIntent
如果使用同一个intent请求PendingIntent多次,得到的PendingIntent仍会是同一个。可以通过以下代码判断PendingIntent是否存在:
/**
* 如果返回null,就代表当前的PendingIntent不存在
*/
private PendingIntent getPendingIntent(Intent i) {
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, i,
PendingIntent.FLAG_NO_CREATE);
return pendingIntent;
}
只是改变了传入的flags的值,PendingIntent.FLAG_NO_CREATE表示:如果当前PendingIntent不存在,就不创建,直接返回一个null。
添加多媒体
File file = Environment.getExternalStorageDirectory();
File imageFile = new File(file, "test.png");// 多媒体数据在本地存储的路径
Bitmap bitmap = BitmapFactory.decodeResource(getResources(),
R.drawable.joker_1);
try {
//将drawable复制到本地,模拟添加一个新多媒体数据
bitmap.compress(CompressFormat.PNG, 100,
new FileOutputStream(imageFile));
//发送广播,上面不可以不考虑。
Intent i = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
i.setData(Uri.parse("file://" + imageFile.getAbsolutePath()));
sendBroadcast(i);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
动态测量
在View未测量完毕之前,获取它的measureHeight,measureWidth都为0,而有些时候却需要在未测量之前得到View的高度。可以在获取高(宽)度之前调用View#measure(0,0),然后再调用View#getMeasureWidth|Height()就可以得到正确值。