[Android]Activity跳转传递任意类型的数据、Activity为SingleTask时代替StartActivityForResult的解决方案…

[Android]Activity跳转传递任意类型的数据、Activity为SingleTask时代替StartActivityForResult的解决方案…

以下内容为原创,欢迎转载,转载请注明

来自天天博客:http://www.cnblogs.com/tiantianbyconan/p/4389674.html

 

需求:在ActivityA跳转到ActivityB,然后在ActivityB操作完返回数据给ActivityA。

这个很普遍的需求,一般情况是使用startActivityForResult的方式去完成。

但是当ActivityB为SingleTask时,这个方式就无效了。你会发现当你执行startActivityForResult后,onActivityResult方法马上就会被回调。至于为什么会出现这种情况,参考这位老兄的文章就可以理解http://blog.csdn.net/sodino/article/details/22101881

解决这种情况的方法,第一种是把ActivityA也设置为SingleTask,然后在ActivityB中startActivity(context, ActivityA.class),然后ActivityA在onNewIntent(Intent intent)方法中去获取传递数据,这样的方式不仅破坏了ActivityA的lauchMode,而且还需要ActivityB中启动指定的ActivityA。

所以,如果能把ActivityA的当前对象(实现某个接口)传到ActivityB中,然后ActivityB中通过接口直接回调那就解决问题了。

但是问题是怎么把当前对象传过去,使用Intent显然不行。

思路是维护一个StoragePool,里面可以暂存需要传递的数据。相当于一个暂存区,ActivityA跳转前,把数据放入这个暂存区,获得一个唯一标识,然后把这个唯一标识使用Intent的方式传递给ActivityB,然后ActivityB拿到这个唯一标识后去暂存区去取数据就好了。

暂存区StoragePool代码如下:

 1 /**
 2  * Author: wangjie
 3  * Email: tiantian.china.2@gmail.com
 4  * Date: 3/30/15.
 5  */
 6 public class StoragePool {
 7     /**
 8      * key   -- 标识是哪一个intent的(UUID)
 9      *
10      *         |- key -- 存储的对象标识(StorageKey,使用UUID唯一)
11      * value --|
12      *         |- value -- 存储的内容
13      */
14     private static ConcurrentHashMap<String, HashMap<StorageKey, WeakReference<Object>>> storageMapper = new ConcurrentHashMap<>();
15 
16     private StoragePool() {
17     }
18 
19     public static void storage(String tagUUID, StorageKey key, Object content) {
20         if (null == key || null == content) {
21             return;
22         }
23         HashMap<StorageKey, WeakReference<Object>> extraMapper = storageMapper.get(tagUUID);
24         if (null == extraMapper) {
25             extraMapper = new HashMap<>();
26             storageMapper.put(tagUUID, extraMapper);
27         }
28         extraMapper.put(key, new WeakReference<>(content));
29     }
30 
31     public static Object remove(String tagUUID, StorageKey key) {
32         if (null == key) {
33             return null;
34         }
35         HashMap<StorageKey, WeakReference<Object>> extraMapper = storageMapper.get(tagUUID);
36         if (null == extraMapper) {
37             return null;
38         }
39 
40         WeakReference<Object> ref = extraMapper.remove(key);
41         if (ABTextUtil.isEmpty(extraMapper)) {
42             storageMapper.remove(tagUUID);
43         }
44         return null == ref ? null : ref.get();
45     }
46 
47     public static HashMap<StorageKey, WeakReference<Object>> remove(String tagUUID) {
48         if (null == tagUUID) {
49             return null;
50         }
51         return storageMapper.remove(tagUUID);
52     }
53 
54     public static void clear() {
55         storageMapper.clear();
56     }
57 
58 }

如上代码,StoragePool维护了一个HashMap,key是一个UUID,代表唯一的一个Intent跳转,ActivityA跳转时会把这个UUID传递到ActivityB,ActivityB就是通过这个UUID来获取这次跳转需要传递的数据的。value也是一个HashMap,里面存储了某次跳转传递的所有数据。key是StorageKey,实质上也是一个UUID,value是任意的数据。

跳转前的存储数据和真正的StartActivity都需要使用StorageIntentCenter来进行操作,代码如下:

 1 /**
 2  * Author: wangjie
 3  * Email: tiantian.china.2@gmail.com
 4  * Date: 3/31/15.
 5  */
 6 public class StorageIntentCenter {
 7     public static final String STORAGE_INTENT_CENTER_KEY_UUID = StorageIntentCenter.class.getSimpleName() + "_UUID";
 8     private static final String TAG = StorageIntentCenter.class.getSimpleName();
 9 
10     private Intent intent;
11     private String uuid;
12     private HashMap<StorageKey, Object> extras;
13     private boolean isUsed;
14     public StorageIntentCenter() {
15         intent = new Intent();
16         uuid = java.util.UUID.randomUUID().toString();
17         intent.putExtra(STORAGE_INTENT_CENTER_KEY_UUID, uuid);
18         isUsed = false;
19     }
20 
21     public StorageIntentCenter putExtra(String intentKey, Object content){
22         if (null == content) {
23             return this;
24         }
25         StorageKey storageKey = new StorageKey(content.getClass());
26         intent.putExtra(intentKey, storageKey);
27         if(null == extras){
28             extras = new HashMap<>();
29         }
30         extras.put(storageKey, content);
31         return this;
32     }
33 
34     public void startActivity(Context packageContext, Class<?> cls){
35         if(isUsed){
36             Logger.e(TAG, this + " can not be reuse!");
37             return;
38         }
39         intent.setClass(packageContext, cls);
40         if(!ABTextUtil.isEmpty(extras)){
41             Set<Map.Entry<StorageKey, Object>> entrySet = extras.entrySet();
42             for(Map.Entry<StorageKey, Object> entry : entrySet){
43                 StoragePool.storage(uuid, entry.getKey(), entry.getValue());
44             }
45         }
46         isUsed = true;
47         packageContext.startActivity(intent);
48     }
49 
50 
51 }

每个StorageIntentCenter都维护了一个真正跳转的Intent,一个此次跳转的uuid和所有需要传递的数据。

 

使用方式(以从MainActivity跳转到OtherActivity为例):

MainActivity中:

@AILayout(R.layout.main)
public class MainActivity extends BaseActivity implements ICommunicate {

    private static final String TAG = MainActivity.class.getSimpleName();

    @Override
    @AIClick({R.id.ac_test_a_btn})
    public void onClickCallbackSample(View view) {
        switch (view.getId()) {
            case R.id.ac_test_a_btn:
                new StorageIntentCenter()
                        .putExtra("iCommunicate", this)
                        .putExtra("testString", "hello world")
                        .putExtra("testFloat", 3.2f)
                        .startActivity(context, OtherActivity.class);

                break;
        }
    }

    @Override
    public void hello(String content) {
        Logger.d(TAG, "hello received: " + content);
    }

}

 

OtherActivity继承了BaseActivity。

BaseActivity:

 1 /**
 2  * Author: wangjie
 3  * Email: tiantian.china.2@gmail.com
 4  * Date: 4/2/15.
 5  */
 6 public class BaseActivity extends AIActivity {
 7     private String storageIntentCenterUUID;
 8 
 9     @Override
10     protected void onCreate(Bundle savedInstanceState) {
11         super.onCreate(savedInstanceState);
12 
13         initExtraFromStorage();
14         // remove extra from StoragePool
15         StoragePool.remove(storageIntentCenterUUID);
16     }
17 
18     protected void initExtraFromStorage() {
19     }
20 
21     protected final <T> T getExtraFromStorage(String key, Class<T> contentType) {
22         StorageKey storageKey = (StorageKey) getIntent().getSerializableExtra(key);
23         if (null == storageIntentCenterUUID) {
24             storageIntentCenterUUID = getIntent().getStringExtra(StorageIntentCenter.STORAGE_INTENT_CENTER_KEY_UUID);
25         }
26         return (T) StoragePool.remove(storageIntentCenterUUID, storageKey);
27     }
28 
29 }

Line15:为了防止跳转到OtherActivity后,如果没有去暂存区把数据取出来从而导致暂存区有无用的数据(甚至内存泄漏,暂存区使用软引用也是为了防止这种情况的发生),所以这里提供一个initExtraFromStorage方法让子类重写,子类可以在这个方法中去把数据取出来。然后在initExtraFromStorage方法执行完毕后,再及时把暂存区的数据删除。

Line21~27:这里提供了从暂存区提取数据的方法供子类调用。

 

OtherActivity:

/**
 * Author: wangjie
 * Email: tiantian.china.2@gmail.com
 * Date: 4/2/15.
 */
@AILayout(R.layout.other)
public class OtherActivity extends BaseActivity{
    private static final String TAG = OtherActivity.class.getSimpleName();

    private ICommunicate iCommunicate;
    private String testString;
    private Float testFloat;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    protected void initExtraFromStorage() {
        iCommunicate = getExtraFromStorage("iCommunicate", ICommunicate.class);
        testString = getExtraFromStorage("testString", String.class);
        testFloat = getExtraFromStorage("testFloat", Float.class);
    }

    @Override
    @AIClick({R.id.other_btn})
    public void onClickCallbackSample(View view) {
        switch(view.getId()){
            case R.id.other_btn:
                if(null == iCommunicate){
                    return;
                }
                Logger.d(TAG, "iCommunicate: " + iCommunicate);
                iCommunicate.hello("content from ACTestBActivity!");

                Logger.d(TAG, "testString: " + testString);
                Logger.d(TAG, "testFloat: " + testFloat);
                finish();

                break;
        }
    }
}

如上代码OtherActivity中获取了从MainActivity中传递过来的MainActivity实例,在点击事件发生后通过MainActivity实例进行直接回调。

日志打印如下:

04-03 12:09:52.184  25529-25529/com.wangjie.androidstorageintent D/OtherActivity﹕ iCommunicate: com.wangjie.androidstorageintent.sample.MainActivity@42879ff8
04-03 12:09:52.184  25529-25529/com.wangjie.androidstorageintent D/MainActivity﹕ hello received: content from ACTestBActivity!
04-03 12:09:52.184  25529-25529/com.wangjie.androidstorageintent D/OtherActivity﹕ testString: hello world
04-03 12:09:52.184  25529-25529/com.wangjie.androidstorageintent D/OtherActivity﹕ testFloat: 3.2

MainActivity被回调,并获取了数据“content from ACTestBActivity!”字符串。

 

注:

1. 以上使用的代码已托管到github:https://github.com/wangjiegulu/AndroidStorageIntent

2. 上面的注解实现使用AndroidInject:https://github.com/wangjiegulu/androidInject

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/109499.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 《Effective C++ 》学习笔记——规定10「建议收藏」

    《Effective C++ 》学习笔记——规定10

    2022年1月17日
    46
  • 截止失真放大电路_技术分享:音频功放失真及常见改善方法「建议收藏」

    截止失真放大电路_技术分享:音频功放失真及常见改善方法「建议收藏」音频功放失真是指重放音频信号波形畸变的现象,通常分为电失真和声失真两大类。电失真就是信号电流在放大过程中产生了失真,而声失真是信号电流通过扬声器,扬声器未能如实地重现声音。无论是电失真还是声失真,按失真的性质来分,主要有频率失真和非线性失真两种。其中,引起信号各频率分量间幅度和相位的关系变化,仅出现波形失真,不增加新的频率成分,属于线性失真。而谐波失真(THD)、互调失真(IMD)等可产生新的频率…

    2022年5月20日
    52
  • android学习笔记之ImageView的scaleType属性

    android学习笔记之ImageView的scaleType属性我们知道,ImageView有一个属性叫做scaleType,它的取值一共有八种,分别是:matrix,fitXY,fitStart,fitCenter,fitEnd,center,centerCrop,centerInside。那我们下面一起来看看这八种取值分别代表什么意思。我用两张图片来做demo,这两张图片的分辨率一大一小,图片分别叫做big和small。原图如下:big:small:OK,

    2022年6月15日
    27
  • 自制STLink

    自制STLink前段时间 由于芯片大涨价 手上又没有 STLink 只有 STM32F103c8t 的芯片 在网上借鉴了很多大佬的 DIY 就自己动手画了一个 好像有两个版本 好像新加一个自带串口的功能 但是要用到 STM32F013cbt 内存比较大 总之是比较好一些的 但是我没有芯片 就做了 STM32c8t6 的原理图是借鉴 st 官网和正定原子潘多拉板子上的 stlink 原理图画出来的这是正点原子的原理图这是我的原理图最终 PCB 长这样烧录固件 去别人那里借了一个 STLink 来下载固件打开 STM32ST LINK

    2025年11月15日
    4
  • task scheduler什么意思_女贞子的功效与作用

    task scheduler什么意思_女贞子的功效与作用前言本文隶属于专栏《1000个问题搞定大数据技术体系》,该专栏为笔者原创,引用请注明来源,不足和错误之处请在评论区帮忙指出,谢谢!本专栏目录结构和参考文献请见1000个问题搞定大数据技术体系正文TaskScheduler的核心任务是提交TaskSet到集群运算并汇报结果。(1)为TaskSet创建和维护一个TaskSetManager,并追踪任务的本地性以及错误信息。(2)遇到Straggle任务时,会放到其他节点进行重试。(3)向DAGScheduler

    2022年10月11日
    7
  • UART和USART有区别

    UART和USART有区别UART  UART是一种通用串行数据总线,用于异步通信。该总线双向通信,可以实现全双工传输和接收。在嵌入式设计中,UART用于主机与辅助设备通信,如汽车音响与外接AP之间的通信,与PC机通信包括与监控调试器和其它器件,如EEPROM通信。  UART的功能计算机内部采用并行数据,不能直接把数据发到Modem,必须经过UART整理才能进行异步传输,其过程为:CPU先把准备写入串行设备的数据…

    2022年5月19日
    38

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号