serializable、 LayoutInflater、Context

1. serializable
 1. 什么是  Serializable 接口?

  Serializable 一个对象序列化的接口,一个类只有实现了Serializable接口,它的对象才是可序列化的。因此如果要序列化某些类的对象,这些类就必须实现Serializable接口。而实际上,Serializable是一个空接口,没有什么具体内容,它的目的只是简单的标识一个类的对象可以被序列化。
2.  那进行序列化有什么好处呢?什么情况下需要序列化 ?

   每一个进程都有自己独立的内存,一个进程的1000地址也许是另一个进程的100000地址,所以如何在进程间通信就变得复杂了,对于基本类型的数据比如整数直接传递过去就行了,但是要是字符串的话就要先在目的进程空间中分配一块能容纳该字符串的内存,然后再复制到该内存中。再如果要传递一个类的实例,也是先为该对象分配内存,然后复制一份再传递可以吗?我认为不可以,我至少可以找到一个理由:类中成员除了属性还有方法,即使属性能完整传过去,但还有方法呢?方法是独立于类对象存在的,所以到另一个进程中再引用同一个方法就要出错了,还是因为独立地址空间的原因。Android中通常要在Activity之间传递数据,而根据Android的设计,即使同一个Activity都不一定运行在同一个进程中,所以就要进程间传递数据了,那么到底如何在进程之间传递类对象呢?简单来说可以这样做:在进程A中把类中的非默认值的属性和类的唯一标志打成包(这就叫序列化),把这个包传递到进程B,进程B接收到包后,根据类的唯一标志把类创建出来,然后把传过来的属性更新到类对象中,这样进程A和进程B中就包含了两个完全一样的类对象。
这里说的唯一标志,就是serialVersionUID
相当于java类的身份证。serialVersionUID作用是序列化时保持版本的兼容性,即在版本升级时反序列化仍保持对象的唯一性。
有两种生成方式:
       一个是默认的1L,比如:private static final long serialVersionUID = 1L;
       一个是根据类名、接口名、成员方法及属性等来生成一个64位的哈希字段,比如:
       private static final long serialVersionUID = xxxxL;


2.LayoutInflater

在实际工作中,事先写好的布局文件往往不能满足我们的需求,有时会根据情况在代码中自定义控件,这就需要用到LayoutInflater。
LayoutInflater在Android中是“扩展”的意思,作用类似于findViewById(),不同的是LayoutInflater是用来获得布局文件对象的,而
findViewById()是用来获得具体控件的。LayoutInflater经常在BaseAdapter的getView方法中用到,用来获取整个View并返回。

LayoutInflater的用法有三种:
第一种方法:
 
  
  1. LayoutInflater inflater = LayoutInflater.from(this);  
  2. View layout = inflater.inflate(R.layout.main, null);
第二种方法:
 
  
  1. LayoutInflater inflater = getLayoutInflater();  
  2. View layout = inflater.inflate(R.layout.main, null); 
第三种方法:
 
  
  1. LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);  
  2. View layout = inflater.inflate(R.layout.main, null);  
第一种方法是通过LayoutInflater类直接实例化inflater。
第二种方法是通过Activity的context来调用getLayoutInflater();
第二种方法用于Activity类,而第三种方法主要用于BaseAdapter类,由于BaseAdapter类并不像Activity类有getLayoutInflater()方法可以获得LayoutInflater对象,因此,需要使用Context类的getSystemService方法来获得LayoutInflater对象。

另外补充下,getSystemService是Activity中的方法,根据传入的name来取得对应的服务对象,这些服务名称参数都是Context类中的常量:

传入的Name                              返回的对象                          说明
WINDOW_SERVICE               WindowManager           管理打开的窗口程序
LAYOUT_INFLATER_SERVICE LayoutInflater               取得xml里定义的view
ACTIVITY_SERVICE               ActivityManager            管理应用程序的系统状态
POWER_SERVICE                  PowerManger                电源的服务
ALARM_SERVICE                   AlarmManager              闹钟的服务
NOTIFICATION_SERVICE       NotificationManager      状态栏的服务
KEYGUARD_SERVICE             KeyguardManager         键盘锁的服务
LOCATION_SERVICE              LocationManager          位置的服务,如GPS
SEARCH_SERVICE                 SearchManager             搜索的服务
VEBRATOR_SERVICE             Vebrator                       手机震动的服务
CONNECTIVITY_SERVICE      Connectivity                  网络连接的服务
WIFI_SERVICE                      WifiManager                  Wi-Fi服务
TELEPHONY_SERVICE            TeleponyManager         电话服务


3. Context
摘自:http://www.cnblogs.com/smalltigerlee/archive/2011/11/10/2244324.html
  Context字面意思上下文,位于framework package的android.content.Context中,其实该类为LONG型,类似Win32中的Handle句柄,很多方法需要通过 Context才能识别调用者的实例,比如说Toast的第一个参数就是Context,一般在Activity中我们直接用this代替,代表调用者的 实例为Activity,而到了一个button的onClick(View view)等方法时,我们用this时就会报错,所以我们可能使用ActivityName.this来解决,主要原因是因为实现Context的类主要有Android特有的几个模型,Activity、Service以及BroadcastReceiver。
  Context提供了关于应用环境全局信息的接口。它是一个抽象类,它的执行被Android系统所提供。它允许获取以应用为特征的资源和类型。同时启动应用级的操作,如启动Activity,broadcasting和接收intents。
两种类型的Context
   在android中context可以作很多操作,但是最主要的功能是加载和访问资源在android中有两种context,一种是 application context,一种是activity context,通常我们在各种类和方法间传递的是activity context。比如一个activity的onCreate。
protected void onCreate(Bundle state) {
super.onCreate(state); 
TextView label = new TextView(this);
//传递context给view control
label.setText("Leaks are bad"); 
setContentView(label);
}
把activity context传递给view,意味着view拥有一个指向activity的引用,进而引用activity占有的资源:view hierachy, resource等。
内存泄露
  这样如果context发生内存泄露的话,就会泄露很多内存。这里泄露的意思是gc没有办法回收activity的内存。
  当屏幕旋转的时候,系统会销毁当前的activity,保存状态信息,再创建一个新的。比如我们写了一个应用程序,它需要加载一个很大的图片,我们不希望每次旋转屏幕的时候都销毁这个图片,重新加载。实现这个要求的简单想法就是定义一个静态的Drawable,这样Activity 类创建销毁图片始终保存在内存中。实现类似:
public class myactivity extends Activity {
private static Drawable sBackground;
protected void onCreate(Bundle state) {
super.onCreate(state);
 
TextView label = new TextView(this);
label.setText("Leaks are bad");
 
if (sBackground == null) {
sBackground = getDrawable(R.drawable.large_bitmap);
}
label.setBackgroundDrawable(sBackground);//drawable attached to a view
setContentView(label);
}
}
这段程序看起来很简单,但是却问题很大。当屏幕旋转的时候会有leak(即gc没法销毁activity)。我们刚才说过,屏幕旋转的时候系统会销毁当前的activity。但是当drawable和view关联后,drawable保存了view的 reference,即sBackground保存了label的引用,而label保存了activity的引用。既然drawable不能销毁,它所引用和间接引用的都不能销毁,这样系统就没有办法销毁当前的activity,于是造成了内存泄露。gc对这种类型的内存泄露是无能为力的。避免这种内存泄露的方法是避免activity中的任何对象的生命周期长过activity,避免由于对象对 activity的引用导致activity不能正常被销毁。
为了防止内存泄露,我们应该注意以下几点:
  1. 不要让生命周期长的对象引用activity context,即保证引用activity的对象要与activity本身生命周期是一样的
  2. 对于生命周期长的对象,可以使用application context
  3. 避免非静态的内部类,尽量使用静态类,避免生命周期问题,注意内部类对外部对象引用导致的生命周期变化
application context
我们可以使用application context。application context伴随application的一生,与activity的生命周期无关。application context可以通过Context.getApplicationContext或者Activity.getApplication方法获取。
而制造Application context的方法在这里可以找到
http://stackoverflow.com/questions/708012/android-how-to-declare-global-variables/708317#708317
  Java里面通常是用一个static的变量(例如singleton之类的)来同步activity之间(程序里面类之间)的状态。在android里面比较靠谱的做法是用application context来关联这些状态。
  做一个你自己的application context需要继承android.app.Application,然后在app的manifest里面说明这个类。android会自动帮你创建你这个类的实例,接着你用Context.getApplicationContext()方法就能在各个activity里
面获得这个application context了。
class MyApp extends Application {
  private String myState;
  public String getState(){
    return myState;
  }
  public void setState(String s){
    myState = s;
  }
}
class Blah extends Activity {
  @Override
  public void onCreate(Bundle b){
    ...
    MyApp appState = ((MyApp)getApplicationContext());
    String state = appState.getState();
    ...
  }
} 

下面介绍Context的一些get方法,通过这些get方法可以获取应用环境全局信息:

1.public abstract Context getApplicationContext ()

Return the context of the single, global Application object of the current process.

2.public abstract ApplicationInfo getApplicationInfo ()

Return the full application info for this context's package.

3.public abstract ContentResolver getContentResolver ()

Return a ContentResolver instance for your application's package.

4.public abstract PackageManager getPackageManager ()

Return PackageManager instance to find global package information.

5.public abstract String getPackageName ()

Return the name of this application's package.

6.public abstract Resources getResources ()

Return a Resources instance for your application's package.

7.public abstract SharedPreferences getSharedPreferences (String name, int mode)

Retrieve and hold the contents of the preferences file 'name', returning a SharedPreferences through which you can retrieve and modify its values. Only one instance of the SharedPreferences object is returned to any callers for the same name, meaning they will see each other's edits as soon as they are made.

8.public final String getString (int resId)

Return a localized string from the application's package's default string table.

9.public abstract Object getSystemService (String name)

Return the handle to a system-level service by name. The class of the returned object varies by the requested name.




你可能感兴趣的:(android)