1. 程式人生 > >如何在Activity間傳遞資料

如何在Activity間傳遞資料

1、基於訊息的通訊機制 Intent------bundle,extra

用這種方式一般而言,傳遞一些簡單的型別是比較容易的,例如int,string等

詳細介紹下Intent機制

Intent包含兩部分:

1)目的【action】------要去到哪裡去

2)內容【category、data】------路上帶些什麼,區分性資料和內容性資料

簡單資料傳遞:

這裡以ActivityA向ActivityB傳遞資料為例

Intent intent = new Intent(context, ActivityB.class);

//如果context上下文不是Activity的話, 需要新增下面這個flag
if (!(context instanceof Activity)) {
  intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}

//新增要傳遞的資料
intent.putExtra(key, value);

//或則將資料打包進Bundle裡
Bundle bundle = new Bundle();

bundle.putString(key, value);

intent.putExtras(bundle);

context.startActivity(intent);

在ActivityB中

public void onCreate(Bundle savedInstanceState) {
  //得到傳遞過來的資料
  Intent intent=new Intent();

  Bundle bundle =intent.getExtras();

  //通過getXXX方法來獲取key對應的value
  bundle.getXXX(key); //intent.getXXX(key);

}

資料型別有限,遇到不可序列化的資料Bitmap和Inputstream等,或者是LinkList等連結串列資料型別就不太好用了

2、使用static靜態變數傳遞資料(謹慎使用)



我們千萬不要以為Davlik虛擬機器的垃圾回收器會幫助我們回收不需要的記憶體垃圾。事實上,回收器並不可靠, 尤其是手機上,是更加的不可靠。 因此,除非我們要使自己的程式變得越來越糟糕,否則儘量遠離static。
如果經常使用static的Bitmap、Drawable等變數,可能就會丟擲一個在Android系統中非常著名的異常:

ERROR/AndroidRuntime(4958): Caused by: Java.lang.OutOfMemoryError: bitmap size exceeds VM budget

使用方法

在目標activity中宣告靜態變數,但必須是public修飾的

public class OtherActivity extends Activity {
        //定義靜態變數
        public static String name;
        public static int age;

        private TextView textview;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            // TODO Auto-generated method stub
            super.onCreate(savedInstanceState);
            setContentView(R.layout.other);
            textview = (TextView)findViewById(R.id.msg);
            textview.setText("name:    "+name+"\n"+"age:    "+age);
        }

    }

在其他activity中可以直接使用靜態變數傳遞資料給目標activity

public class MainActivity extends Activity {

        private Button button;
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            button = (Button)this.findViewById(R.id.st);
            button.setOnClickListener(new OnClickListener() {

                public void onClick(View v) {
                    // TODO Auto-generated method stub
                    Intent intent = new Intent();
                    intent.setClass(MainActivity.this, OtherActivity.class);
                    OtherActivity.name="mayi";//直接呼叫靜態變數
                    OtherActivity.age=23;
                    startActivity(intent);
                }
            });
        }

    }

3、使用全域性變數在Activity之間傳遞資料


在整個Android程式中,有時需要儲存某些全域性的資料(如:使用者資訊),方便在程式的任何地方呼叫。在Activity之間資料傳遞中有一種比較使用的方式,就是全域性物件,使用過J2EE的都應該知道JavaWeb的四個作用域,其中Application域在應用程式的任何地方都可以使用和訪問,除非是Web伺服器停止,Android中的全域性物件非常類似於JavaWeb中的Application域,除非是Android應用程式清除記憶體,否則全域性物件將一直可以訪問。

在啟動Application時,系統會建立一個PID,即程序ID,所有的Activity就會在此主程序上執行。所以,在同一Application中所有的Activity都可以通過Activity.getApplication()方法獲取到同一個Application物件,繼承Application類,即可訪問自定義資料。

使用Application傳遞資料步驟如下:

  1. 建立新class,取名MyApp,繼承android.app.Application父類,並在MyApp中定義需要儲存的屬性,如:使用者名稱,使用者型別;
  2. 在Activity中,通過Activity.getApplication()方法獲取到MyApp物件(需要強制轉換),對其資料進行操作;
  3. 修改AndroidManifest.xml檔案中的application節點的android:name屬性(android:name=".MyApp")。
步驟一:
public class MyApp extends Application {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
setName("Dick");
}
}

步驟二:
public class MainActivity extends Activity {
private Button btn;
private MyApp myApp;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn=(Button)this.findViewById(R.id.btn);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
myApp=(MyApp)getApplication();
myApp.setName("jack");
Intent intent=new Intent(MainActivity.this, OtherActivity.class);
startActivity(intent);
}
});
}
}

步驟三:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="cn.bgxt.staticchuandi"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="17" />
<application
android:name=".MyApp"
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="cn.bgxt.staticchuandi.MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".OtherActivity"/>
</application>
</manifest>

4、使用剪下板在Activity之間傳遞物件資料

Activity1:

                Person person = new Person("wulianghuan","22");
                //將物件轉換成字串
                ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
                String base64String = "";

                try {
                    ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
                    objectOutputStream.writeObject(person);
                    base64String = Base64.encodeToString(byteArrayOutputStream.toByteArray(), Base64.DEFAULT);
                    objectOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                //從Android系統中呼叫剪下板的服務
                ClipboardManager clipboardManager = (ClipboardManager)
                getSystemService(Context.CLIPBOARD_SERVICE);
                //在剪下板中放入要傳遞的資料
                clipboardManager.setText(base64String);
                //定義一個意圖
                Intent intent = new Intent(Activity1.this,Activity2.class);
                startActivity(intent);

Activity2:
        text_name = (TextView) findViewById(R.id.name);
        //從Android系統中呼叫剪下板的服務
        ClipboardManager clipboardManager = (ClipboardManager)
        getSystemService(Context.CLIPBOARD_SERVICE);
        String getString = clipboardManager.getText().toString();
        //字串還原成物件
        byte[] base64_byte = Base64.decode(getString, Base64.DEFAULT);
        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(base64_byte);
        try {
            ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);
            Person person = (Person)objectInputStream.readObject();
            Log.i("OtherActivity", person.toString());
            //設定文字框的資料
            text_name.setText(person.toString());
        } catch (StreamCorruptedException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

5、基於外部儲存的傳輸(File/Preference/SQLite,如果要針對第三方應用需要Content provider)

SQLite: SQLite是一個輕量級的資料庫,支援基本SQL語法,是常被採用的一種資料儲存方式。Android為此資料庫提供了一個名為SQLiteDatabase的類,封裝了一些操作資料庫的API。

SharedPreference: 除SQLite資料庫外,另一種常用的資料儲存方式,其本質就是一個xml檔案,常用於儲存較簡單的引數設定。

File: 即常說的檔案(I/O)儲存方法,常用語儲存大數量的資料,但是缺點是更新資料將是一件困難的事情。

ContentProvider: ContentProvider是安卓平臺中,在不同應用程式之間實現資料共享的一種機制。一個應用程式如果需要讓別的程式可以操作自己的資料,即可採用這種機制。並且此種方式忽略了底層的資料儲存實現,ContentProvider提供了一種統一的通過Uri實現資料操作的方式。在處處見“雲”的今天,程式間的資料互動需求令ContentProvider儲存機制變成必不可少的一部分。

6、基於Ipc的通訊機制

context與service之間的傳輸,如Activity與Service之間的通訊