android知识点

1.用layout_weight实现自适应屏幕

 

一、细说layout_weight
    目前最为推荐的Android多屏幕自适应解决方案。
    该属性的作用是决定控件在其父布局中的显示权重,一般用于线性布局中。其值越小,则对应的layout_width或layout_height的优先级就越高,一般横向布局中,决定的是layout_width的优先级;纵向布局中,决定的是layout_height的优先级。
    传统的layout_weight使用方法是将当前控件的layout_widthlayout_height都设置成fill_parent,这样就可以把控件的显示比例完全交给layout_weight;这样使用的话,就出现了layout_weight越小,显示比例越大的情况。不过对于2个控件还好,如果控件过多,且显示比例也不相同的时候,控制起来就比较麻烦了,毕竟反比不是那么好确定的。
    于是就有了现在最为流行的0px设值法。看似让人难以理解的layout_height=0px的写法,结合layout_weight,却可以使控件成正比例显示,轻松解决了当前Android开发最为头疼的碎片化问题之一。
    先看下面的stylesstyle_layout.xml

 

代码片段,双击复制
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<?xml version="1.0" encoding="utf-8"?>                                          
<resources>  
 
<!-- 全屏幕拉伸-->
  <style name="layout_full">  
    <item name="android:layout_width">fill_parent</item>  
    <item name="android:layout_height">fill_parent</item>  
  </style>
   
<!-- 固定自身大小-->
  <style name="layout_wrap">  
    <item name="android:layout_width">wrap_content</item>  
    <item name="android:layout_height">wrap_content</item>  
  </style>
 
<!-- 横向分布-->
  <style name="layout_horizontal" parent="layout_full">  
    <item name="android:layout_width">0px</item>  
  </style>
    
<!-- 纵向分布-->
  <style name="layout_vertical" parent="layout_full">  
    <item name="android:layout_height">0px</item>  
  </style>
         
</resources>  

 

可以看到,layout_widthlayout_height两个属性被我封装成了4style
    根据实际布局情况,选用当中的一种,不需要自己设置,看过我前一个ActivityGroupDemo的同学应该非常熟悉了
    然后我的Demo的布局如下(weight_layout.xml

 

代码片段,双击复制
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        style="@style/layout_full"
        android:orientation="vertical">
        <LinearLayout
                style="@style/layout_vertical"
                android:layout_weight="1"
                android:orientation="horizontal">
                 <View
                         style="@style/layout_horizontal"
                         android:background="#aa0000"
                         android:layout_weight="1"/>
                 <View
                         style="@style/layout_horizontal"
                         android:background="#00aa00"
                         android:layout_weight="4"/>
                 <View
                         style="@style/layout_horizontal"
                         android:background="#0000aa"
                         android:layout_weight="3"/>
                 <View
                         style="@style/layout_horizontal"
                         android:background="#aaaaaa"
                         android:layout_weight="2"/>                
        </LinearLayout>
        <LinearLayout
                style="@style/layout_vertical"
                android:layout_weight="2"
                android:orientation="vertical">
                <View
                         style="@style/layout_vertical"
                         android:background="#ffffff"
                         android:layout_weight="4"/>       
                 <View
                         style="@style/layout_vertical"
                         android:background="#aa0000"
                         android:layout_weight="3"/>
                 <View
                         style="@style/layout_vertical"
                         android:background="#00aa00"
                         android:layout_weight="2"/>
                 <View
                         style="@style/layout_vertical"
                         android:background="#0000aa"
                         android:layout_weight="1"/>
 
        </LinearLayout>
</LinearLayout>


整个界面布局看起来非常直观,只是嵌套的逻辑要自己理下。显示效果如下图,其中左面一个是480x800的界面,右面的是320x480的界面(后面的图也如此),可以看出显示比例和代码中完全一致,我就不多说了,大家对照下就能看出来了。
1.png

 

2.Timer  and  TimerTask  来定时更新一个程序

  Timer timer = new Timer("");

  timer.schedule(new TimerTask(){},Date date ,long peroid);


  Date表示要在什么时间运行,peroid表示每隔一段时间之后就会运行一次,这里如果只想运行一次的话,就不要定义 long peroid 参数了。

 

3.ANR --- 程序不反应

这个会在  data/anr/ trace .txt 中,我们可以分析这个文件来看一下为什么会出现这个问题,如下图所示:

包括了出现的时间,以及在哪个包中出现的,有在 哪个 .java文件,这样就很容易定位。看一下是不是 IO 内存泄露  堵塞

4. Activity 和 Task 的启动模式

standard  每次都会新建,每个Task都可以有,且每个Task都可以有多个实例(每个Task都可以有,且可以有多个)
singleTop 当前实例如果在栈顶,就不新建实例,调用其OnNewIntent。 如不在栈顶,则新建实例 (每个Task都可以有,且可以有多个,在栈顶时可复用)
singleTask 新建一个Task,如果已经有其他的Task并且包含该实例,那就直接调用那个Task的实例。(只有一个Task中会有)
singleInstance 新建一个Task,且在该Task中只有它的唯一一个实例。 (只有一个Task会有,且该Task中只有它)

5. 通过intent传递 二进制数据---------------------分解成字节流以便在网络上传输,分开,合并

  通过实现序列化接口

  Android来说传递复杂类型,主要是将自己的类转换为基础的字节数组,Activity之间传递数据是通过Intent实现的。 Android序列化对象主要有两种方法,实现Serializable接口、或者实现Parcelable接口。实现Serializable接口是Java
SE本身就支持的,而Parcelable是Android特有的功能,本类被用作封装数据的容器,效率比实现Serializable接口高,,封装后的数据可以通过Intent或IPC传递

在SDK中 Parcelable类的概述是这样的:Interface for classes whose instances can be written to and restored from a 
Parcel
. Classes implementing the Parcelable interface must also have a static field called 
CREATOR
, which is an object implementing the
Parcelable.Creator
interface.

 

这个接口的实例是通过Parcel进行存储的,在使用Parcelable的时候必须使用Parcelable.Creator。

 

下面上代码:

 

首先修改main.xml,增加一个button

 

<?xml version="1.0" encoding="utf-8"?>
<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView
android:id="@+id/text"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/hello"
/>
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Parcelable">
</Button>
</LinearLayout>

 





然后是主Activity ParcelableTest.java,这个类显示UI,并通过button点击事件启动另一个Activity -- ParcelableTest2,同时通过Parcelable接口传递一些数据。

 

 

 

package parcelable_test.com;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
publicclassParcelableTestextendsActivityimplementsOnClickListener{
publicstaticfinalString KEY ="key";
privateButton button;
publicstaticfinalString TAG ="Parcelable";
@Override
publicvoid onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
init();
Log.d(TAG,"ParcelableTest");
}
privatevoid init(){
button =(Button)findViewById(R.id.button);
button.setOnClickListener(this);
}
privatevoid fun(){
Log.d(TAG,"fun");
Person mPerson =newPerson();
mPerson.setName("tom");
mPerson.setAge(25);
Intent mIntent =newIntent(this,parcelable_test.com.ParcelableTest2.class);
Bundle mBundle =newBundle();
mBundle.putParcelable(KEY, mPerson);
mIntent.putExtras(mBundle);
startActivity(mIntent);
}
@Override
publicvoid onClick(View v){
switch(v.getId()){
case R.id.button:
fun();
break;
default:
break;
}
}
}

 


ParcelableTest2.java,这个类用于获取ParcelableTest传出的数据,并显示在UI上。
[java] view plaincopyprint? 
package parcelable_test.com; 
import android.app.Activity; 
import android.os.Bundle; 
import android.util.Log; 
import android.widget.TextView; 
public class ParcelableTest2 extends Activity{ 
private static final String TAG = ParcelableTest.TAG; 
@Override 
public void onCreate(Bundle savedInstanceState) { 
super.onCreate(savedInstanceState); 
setContentView(R.layout.main); 
Log.d(TAG, "ParcelableTest2"); 
TextView textView = new TextView(this); 
Person mPerson = (Person)getIntent().getParcelableExtra(ParcelableTest.KEY); 
textView.setText("name = " + mPerson.getName() + " age = " + mPerson.getAge()); 
setContentView(textView); 
} 
} 

下面就是最重要的类Person,Person类引用了Parcelable接口
[java] view plaincopyprint? 
package parcelable_test.com; 
import android.os.Parcel; 
import android.os.Parcelable; 
import android.util.Log; 
public class Person implements Parcelable{ 
private String name; 
private int age; 
private static final String TAG = ParcelableTest.TAG; 
public String getName() { 
return name; 
} 
public void setName(String name) { 
this.name = name; 
} 
public int getAge() { 
return age; 
} 
public void setAge(int age) { 
this.age = age; 
} 
public static final Parcelable.Creator<Person> CREATOR = new Creator<Person>() { 
@Override 
public Person createFromParcel(Parcel source) { 
Log.d(TAG,"createFromParcel"); 
Person mPerson = new Person(); 
mPerson.name = source.readString(); 
mPerson.age = source.readInt(); 
return mPerson; 
} 
@Override 
public Person[] newArray(int size) { 
// TODO Auto-generated method stub 
return new Person[size]; 
} 
}; 
@Override 
public int describeContents() { 
// TODO Auto-generated method stub 
Log.d(TAG,"describeContents"); 
return 0; 
} 
@Override 
public void writeToParcel(Parcel dest, int flags) { 
// TODO Auto-generated method stub 
Log.d(TAG,"writeToParcel"); 
dest.writeString(name); 
dest.writeInt(age); 
} 
} 
最后在AndroidManifest.xml加入<activity android:name=".ParcelableTest2"></activity>

输出的log如下:
05-18 16:09:47.243 I/ActivityManager( 59): Starting activity: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=parcelable_test.com/.ParcelableTest } 
05-18 16:09:47.383 D/Parcelable( 337): ParcelableTest 
05-18 16:09:48.003 I/ActivityManager( 59): Displayed activity parcelable_test.com/.ParcelableTest: 724 ms (total 724 ms) 
05-18 16:09:49.263 D/Parcelable( 337): fun 
05-18 16:09:49.263 D/Parcelable( 337): writeToParcel 
05-18 16:09:49.273 I/ActivityManager( 59): Starting activity: Intent { cmp=parcelable_test.com/.ParcelableTest2 (has extras) } 
05-18 16:09:49.453 D/Parcelable( 337): ParcelableTest2 
05-18 16:09:49.453 D/Parcelable( 337): createFromParcel 
05-18 16:09:49.952 I/ActivityManager( 59): Displayed activity parcelable_test.com/.ParcelableTest2: 562 ms (total 562 ms) 
通过log可知程序的运行情况,在mBundle.putParcelable(KEY, mPerson);时,调用了Person类中的public void writeToParcel(Parcel dest, int flags)方法,并向dest写数据,在 Person mPerson = (Person)getIntent().getParcelableExtra(ParcelableTest.KEY);的时候,调用了Person类中的public Person createFromParcel(Parcel source) 方法,创建了一个Person对象,并给这个对象的属性赋值,这里的Parcel source和Parcel dest,是相同的,然后返回这个Person对象。最后就可以打印出mPerson的属性信息了。

5.产生内存泄露的地方

 

1.数据库的 cursor 没有关闭 数据库的 2.构造 adapter 时,没有使用缓存 contentview 构造 没有使用缓存

的优化问题-----减少创建 view 的对象 充分使用 contentview,可以使 的对象,充分使用 衍生 listview 的优化问题 减少创建 可以使 的过程/ 用一静态类来优化处理 getview 的过程 3.Bitmap 对象不使用时采用 recycle()释放内存 释放内存 4.activity 中的对象的生命周期大于 activity 调试方法:

posted @ 2012-09-28 20:20  张兰云  阅读(195)  评论(0编辑  收藏  举报