【安卓学习之常见问题】 界面(Activity/Fragment)之间的数据传递(Intent/Bundle)(附TransactionTooLargeException问题)
█【安卓学习之常见问题】 界面(Activity/Fragment)之间的数据传递(Intent/Bundle)█相关文章:- ● 【android学习开源项目之BasePopup】BasePopup(PopupWindow)进行二次封装 ● 【android学习开源项目之AndroidAutoSize】AndroidAutoSize和DialogFragment的适配█...
█ 【安卓学习之常见问题】 界面(Activity/Fragment)之间的数据传递(Intent/Bundle)(附TransactionTooLargeException问题)
█ 系列文章目录
提示:这里是收集了安卓学习之常见问题的相关文章
- 【安卓学习之常见问题】从ANR到ConcurrentModificationException(附TransactionTooLargeException问题)
- 【安卓学习之常见问题】 界面(Activity/Fragment)之间的数据传递(Intent/Bundle)(附TransactionTooLargeException问题)
█ 文章目录
█ 读前说明
- 本文通过学习别人写demo,学习一些课件,参考一些博客,’学习相关知识,如果涉及侵权请告知
- 本文只简单罗列相关的代码实现过程
- 涉及到的逻辑以及说明也只是简单介绍,主要当做笔记,了解过程而已
█ 我的问题:数据如何传输
⚡️ 在开发过程中进行数据传输,除了通过网络请求获取,部分数据是之间在本地之间进行传递的,经常会有点错乱,因此在此总结下。
█ 解决问题:
⚡️ 方法一,SharedPreferences
将数据通过android自带的SharedPreferences进行数据保存 (重启App数据不丢失)
SharedPreferences.edit().putString("Token", “123456”).commit();// 保存
SharedPreferences.getString("Token", "")// 获取
可以保存对象吗?当前可以,自己写比较麻烦,网上也有大神将他封装成一个库,可以直接调用使用,如果只是简单的数据信息保存,可以直接用原生的。
⚡️ 方法二,数据库
将数据保存到数据库中 (重启App数据不丢失)
ArrayList<Person> items= (ArrayList<Person>) LitePal.findAll(Person.class);// 保存
LitePal.saveAll(items);// 获取
数据库操作比较复杂,因此直接建议使用第三方库,比如’org.litepal.android:core:2.0.0’
⚡️ 方法三,全局对象
创建一个全局对象即可 (重启App数据丢失)
public class DataManager {
private static volatile DataManager INSTANCE;
List<Person> items = new ArrayList<>();
private DataManager() {
}
public static DataManager getInstance() {
if (INSTANCE == null) {
synchronized (DataManager.class) {
if (INSTANCE == null) {
INSTANCE = new DataManager();
}
}
}
return INSTANCE;
}
public List<Person> getItems() {
return items;
}
public void setItems(List<Person> items) {
this.items = items;
}
}
⚡️ 方法四,Intent/Bundle数据传递
通过Intent/Bundle数据传递到下一个界面 (重启App数据丢失),这个也是本文章主要要记录的数据。
█ 方案四详解:
⚡️ 传递的数据类型
- 启动Activity/Service 时通过Intent传递数据;
- 结束Activity/Fragment返回onActivityResult 时通过Intent传递数据;
- 启动Fragment 时是通过Bundle传递数据;
Intent里面也可以进行传输Bundle对象。
⚡️ 关于Intent和Bundle 的数据封装:
(这边先定义好intent和bundle方便后面使用 )
Person item = new Person ();
List<Person> items = new ArrayList<>();
Bundle bundle = new Bundle();
bundle.putInt("int2",22);
bundle.putInt("String","china22");
bundle.putSerializable("Object2", item);
bundle.putSerializable("List2", (Serializable) items);
Intent intent=new Intent();
intent.putExtra("int",11);
intent.putExtra("String","china");
intent.putExtra("Object",item );
intent.putExtra("List", (Serializable) items);
intent.putExtra("bundle",bundle);
⚡️ 上述1、2情况的传递方式:(intent在前面已经定义好了)
intent.setClass(Activity1.this,Activity2.class);
startActivity(intent);// 情况1
startActivityForResult(intent,requestCode);// 情况1
setResult(requestCode, intent);;// 情况2
getTargetFragment().onActivityResult(requestCode,Activity.RESULT_OK, intent);// 情况2
⚡️ 上述3情况的传递方式:(bundle在前面已经定义好 了)
DialogFragment fragment = new DialogFragment();
fragment.setArguments(bundle);
⚡️ 上述1、2情况的接收:
intent.getIntExtra("int",11);// 针对 intent.putExtra("int",11);
intent.getStringExtra("String","china");// 针对 intent.putExtra("String","china");
(Person) intent.getSerializableExtra("Object",item );// 针对 intent.putExtra("Object",item );
(ArrayList<Person >) intent.getSerializableExtra("List", (Serializable) items);// 针对 intent.putExtra("List", (Serializable) items);
bundle = intent.getBundleExtra("bundle",bundle);// 针对 intent.putExtra("bundle",bundle)
if (bundle != null) {
ArrayList<Person> list = (ArrayList<Person>) bundle.get("List2");
......
}
接下来比较有意思的是:
我们通过intent直接获取bundle的key值,通过bundle直接获取intent的key值
// 针对 bundle.putSerializable("Object2", item);
(Person) intent.getSerializableExtra("Object2",item );
// 针对 bundle.putSerializable("List2", (Serializable) items);
(ArrayList<Person >) intent.getSerializableExtra("List2", (Serializable) items);
// 针对 intent.putExtra("Object",item );
(Person) bundle.get("Object",item );
// 针对 intent.putExtra("List", (Serializable) items);
(ArrayList<Person >) intent.get("List", (Serializable) items);
我们惊奇的发现竟然也可以取出这些数据!!!
也就是说:intent和bundle进行put(保存)数据的时候,是存在同一块map中,
看下源码,我们可以发现:
intent.getSerializableExtra(name)其实就是在调用bundle.getSerializable(name)
因此不管用intent还是bundle都可以,只是调用的接口名称不一样而已
public class Intent implements Parcelable, Cloneable {
private Bundle mExtras;
/**
* Retrieve extended data from the intent.
*
* @param name The name of the desired item.
*
* @return the value of an item previously added with putExtra(),
* or null if no Serializable value was found.
*
* @see #putExtra(String, Serializable)
*/
public Serializable getSerializableExtra(String name) {
return mExtras == null ? null : mExtras.getSerializable(name);
}
● ● ● ● ● ●
}
█ 为什么有些是Intent 有些是Bundle ?
⚡️ 这个暂时不深入研究,至少Intent 中的数据都是存在Bundle 中的,在这里就罗列下代码记录下。
⚡️ 启动Activity/Service 时通过Intent传递数据;
@Override
public void startActivity(Intent intent) {
mBase.startActivity(intent);
}
@Override
public ComponentName startService(Intent service) {
return mBase.startService(service);
}
/** Return the intent that started this activity. */
public Intent getIntent() {
return mIntent;
}
⚡️ 结束Activity/Fragment返回onActivityResult 时通过Intent传递数据;
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
this.mFragments.noteStateNotSaved();
int requestIndex = requestCode >> 16;
if (requestIndex != 0) {
--requestIndex;
String who = (String)this.mPendingFragmentActivityResults.get(requestIndex);
this.mPendingFragmentActivityResults.remove(requestIndex);
if (who == null) {
Log.w("FragmentActivity", "Activity result delivered for unknown Fragment.");
} else {
Fragment targetFragment = this.mFragments.findFragmentByWho(who);
if (targetFragment == null) {
Log.w("FragmentActivity", "Activity result no fragment exists for who: " + who);
} else {
targetFragment.onActivityResult(requestCode & '\uffff', resultCode, data);
}
}
} else {
PermissionCompatDelegate delegate = ActivityCompat.getPermissionCompatDelegate();
if (delegate == null || !delegate.onActivityResult(this, requestCode, resultCode, data)) {
super.onActivityResult(requestCode, resultCode, data);
}
}
}
⚡️ 启动Fragment 时是通过Bundle传递数据;
public class TestFragment extends SupportFragment {
Person person;
public static TestFragment newInstance(Person person ) {
Bundle args = new Bundle();
args.putSerializable("person ", person );
TestFragment fragment = new TestFragment();
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle args = getArguments();
if (args != null) {
Object obj = args.getSerializable("person ");
person= person instanceof Person ? (Person) obj : null;
}
}
● ● ● ● ● ●
}
█ 一个小问题:putExtra和getExtra类型不同会怎么样?(2020-05-26补充)
⚡️ 如果 intent.putExtra(“test”,true);那么 intent.getIntExtra(“test”,100)等于多少?
我们都知道,intent.getBooleanExtra(“test”,false),会等于true;
而intent.getIntExtra(“test”,100)等于多少?经过测试,是等于100,即默认值。
⚡️ 为什么有这个问题?
恰好看到一段代码,通过intent传值来判断,通知栏消息要跳转到哪个页面,因此才有此疑问,那么这样写的后果,将push永远为0,永远无法执行跳转功能,如下:
█ 第二个小问题?传递的数据太大时,怎么办?(2021-04-26补充)
⚡️ 当intent.putExtra传递的数据太大时,怎么办?
【安卓学习之常见问题】从ANR到ConcurrentModificationException
█ 相关资料
提示:这里是参考的相关文章
- 2019-03-06 Android传值Intent和Bundle区别 - 限量版爱 - 博客园
- 2018-12-03 TransactionTooLargeException: data parcel size xxx bytes原因与解决方案_迎风致万里的博客-CSDN博客
- Android 开发太难了,这异常竟然捕获不到?跳转Activity时,携带数据过多
█ 免责声明
博主分享的所有文章内容,部分参考网上教程,引用大神高论,部分亲身实践,记下笔录,内容可能存在诸多不实之处,还望海涵,本内容仅供学习研究使用,切勿用于商业用途,若您是部分内容的作者,不喜欢此内容被分享出来,可联系博主说明相关情况通知删除,感谢您的理解与支持! |
---|
提示:转载请注明出处:
https://blog.csdn.net/ljb568838953/article/details/104657403
更多推荐
所有评论(0)