碎雨(三)

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()就可以得到正确值。



你可能感兴趣的:(碎雨(三))