Activity跳轉時傳遞資料的騷操作

liuzh發表於2019-01-15

=====

在掘金群裡小夥伴的提醒下, 發現在activity意外銷燬重啟的情況下, 會造成拿不到資料的問, 所以文章內介紹的內容, 暫時隨意當做高風險野路子看看~

一不小心隔了大半年沒有寫部落格了,這大半年從一個小菜雞變成了一個大(pang)菜雞。。。好吧,進入正題吧

  • Q:MainActivity跳到TargetActivity時附帶資料要怎麼做?

  • A:不就是intent附帶資料嗎?或者sp/檔案存一下等等方式....

  • Q:那如果是沒有實現序列化的資料呢?

  • A:序列化一下唄...

  • Q:業務原因/歷史原因....這個Bean類要實現序列化的話牽扯到太多東西了,改動成本太大,例如:Bean類裡面有Data類,Data類裡面又有Other類........這樣的問題

  • A:..???..???...????!!!!!??!

開始埋頭苦想

這埋的雷夠巧妙啊,不過難不倒我,這個靈機一動動~誒,我可以這樣做:

在跳轉的時候,先用一個靜態變數引用資料,等TargetActivity起來的時候,再把靜態變數置為null,哎呀,一不小心還注意到了要避免記憶體洩漏,太棒了!


public class TargetActivity extends AppCompatActivity {

    // 臨時承載資料
    private static Bean sBean;
    // activity起來的時候真正引用到資料
    private Bean mBean;

    /**
     * 啟動TargetActivity必須統一走這個方法
     * @param context c
     * @param bean bean
     */
    public static void start(Context context, Bean bean) {
        Intent starter = new Intent(context, TargetActivity.class);
        // 靜態變數先拿著
        sBean = bean;
        context.startActivity(starter);
    }


    {
        // 成員變數拿到引用
        mBean = sBean;
        // 靜態變數置空,防止記憶體洩漏
        sBean = null;
    }

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_target);
        Log.i("LiuZh", "onCreate: " + mBean.name + "  " + mBean.age);
    }
}

複製程式碼

總感覺這種拍腦袋就搞出來的騷操作有點不太對勁啊

對了!如果有兩個地方依次相接呼叫TargetActivity.start(Context,Bean)方法,第一個start呼叫還沒開始建立activity呢,第二個start就把sBean重新賦值了,那兩個activity就拿到了同一個資料.....不行,這樣就亂了,得規避一下這問題---(至於有沒有允許啟動多個相同activity的需求,反正我有....也總會有的)

這樣的話,我可以把start方法鎖住,然後執行完了sBean = null;這個語句再解鎖?

那要怎麼寫呢,那就給start方法加個synchronized吧,startActivity語句走完就阻塞住,等activity起來拿到資料的時候就解阻塞,好像可以

接下來就是,要怎麼阻塞呢?而且阻塞的話千萬不能在主執行緒,也就意味著我需要在子執行緒內鎖程式碼塊,在子執行緒內阻塞。這樣的話,就在子執行緒用一個while(flag)吧,activity拿完資料就修改flag通知一下,哦了,啪啪就是敲

public class TargetActivity extends AppCompatActivity {
   // 臨時承載資料
    private static Bean sBean;
    // activity起來的時候真正引用到資料
    private Bean mBean;

    private static boolean sNextStartTaskFlag = false;

    /**
     * 啟動TargetActivity必須統一走這個方法
     *
     * @param context c
     * @param bean    bean
     */
    public static void start(final Context context, final Bean bean) {
        new Thread() {
            @Override
            public void run() {
                super.run();
                synchronized (TargetActivity.class) {
                    sNextStartTaskFlag = false;
                    Intent starter = new Intent(context, TargetActivity.class);
                    // 靜態變數先拿著
                    sBean = bean;
                    context.startActivity(starter);
                    // 阻塞住
                    while (!sNextStartTaskFlag) ;// do nothing
                }
            }
        }.start();
    }


    {
        // 成員變數拿到引用
        mBean = sBean;
        // 靜態變數置空,防止記憶體洩漏
        sBean = null;
        // 我ok了, 下一個start可以走了
        sNextStartTaskFlag = true;
    }

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_target);
        Log.i("LiuZh", "onCreate: " + mBean.name + "  " + mBean.age);
    }

}
複製程式碼

得,這樣應該沒啥問題了,走你

  • MainActivity佈局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="vertical"
    tools:context="com.example.activitydemo.MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="startTargetActivity"
        android:text="走 你" />


</LinearLayout>

複製程式碼
  • MainActivity
public class MainActivity extends AppCompatActivity {

    private Activity mContext;
    private Bean mBean = new Bean();

    {
        mContext = this;
        mBean.name = "LiuZh";
        mBean.age = 22;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    public void startTargetActivity(View view) {
        TargetActivity.start(mContext, mBean);
    }


}

複製程式碼
  • 走你

走你

Logcat有Log

哦喲,好像還挺不錯的,好,作為一個有追求的小碼渣,還是來自測一下吧,用多個執行緒來瘋狂呼叫一下的start方法:

    public void startTargetActivity(View view) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 2; i++) {
                    Bean bean = new Bean();
                    bean.name = "thread_1_LiuZh_" + i;
                    bean.age = i;
                    TargetActivity.start(mContext, bean);
                    Log.i("LiuZh", "Thread_1: " + i);
                }
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 2; i++) {
                    Bean bean = new Bean();
                    bean.name = "thread_2_LiuZh_" + i;
                    bean.age = i;
                    TargetActivity.start(mContext, bean);
                    Log.i("LiuZh", "Thread_2: " + i);
                }
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 2; i++) {
                    Bean bean = new Bean();
                    bean.name = "thread_3_LiuZh_" + i;
                    bean.age = i;
                    TargetActivity.start(mContext, bean);
                    Log.i("LiuZh", "Thread_3: " + i);
                }
            }
        }).start();
    }

複製程式碼
  • 走你

瘋狂自測

哦了,從Log看起來沒問題了,看看是不是有6個activity起來了吧,看模擬器去吧

啥?圖?

沒圖!自個跑一遍吧

結語

  • 更多內容歡迎訪問我的主頁我的部落格
  • 覺得本文/本Demo對你有所幫助,請不要忘了點一下文末的"♡"讓他變成"❤"
  • 文中有不妥/錯誤之處,還請見諒並指出
  • 學習就是耐住寂寞不斷踩坑,多動手敲就能有更多的知識經驗和肩椎脊柱受損T_T

相關文章