Android 四大组件:Activity、Service、ContentProvider、Broadcast Receiver。

在Android App开发中,跟UI相关使用的最多的莫过于Activity了。

一个Activity 启动另一个Activity时,可以使用Intent,其包含了一组方法方便携带一些参数:

1、MainActivity中包含一个按钮,点击打开DetailActivity:

public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);View detailBtn = findViewById(R.id.detail_btn);detailBtn.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {onDetailBtnClick();}});}private void onDetailBtnClick() {Intent intent = new Intent(this, DetailActivity.class);//传参intent.putExtra(ExtraKeyConstans.NAME, "CXC");intent.putExtra(ExtraKeyConstans.AGE, 22);/*//传参Bundle extras = new Bundle();extras.putString(ExtraKeyConstans.NAME, "CXC");extras.putInt(ExtraKeyConstans.AGE, 22);intent.putExtras(extras);*/startActivity(intent);}
}

2、DetailActivity中仅包含一个DetailFragment,将从MainActivity中携带的参数传入其中(直接透传)。

public class DetailActivity extends AppCompatActivity {private static final String TAG = "DetailActivity";private static final String TAG_DETAIL_FRAGMENT = "detailFragmentTag";@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_detail);Intent intent = getIntent();//获取参数/*//方式一:逐一获取,并传给FragmentString tUserName = intent == null ? "" : intent.getStringExtra(ExtraKeyConstans.NAME);int tUserAge = intent == null ? -1 : intent.getIntExtra(ExtraKeyConstans.AGE, -1);DetailFragment detailFragment = DetailFragment.newInstance(tUserName, tUserAge);Log.d(TAG, "-->onCreate()--tUserName:" + tUserName);Log.d(TAG, "-->tUserAge()--tUserAge:" + tUserName);*///方式二:不获取,仅透传给Fragment//如果所传入的数据对当前Activity无用,直接透传即可Bundle bundle = intent == null ? null : intent.getExtras();DetailFragment detailFragment = DetailFragment.newInstance(bundle);FragmentManager fragmentManager = getSupportFragmentManager();FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();fragmentTransaction.add(R.id.fragment_container,detailFragment,TAG_DETAIL_FRAGMENT);fragmentTransaction.commitAllowingStateLoss();}
}

在DetailFragment中获取该参数并Log输出:

public class DetailFragment extends Fragment {private static final String TAG = "DetailFragment";private String userName;private int userAge;public static DetailFragment newInstance(String userName, int userAge) {Bundle args = new Bundle();args.putString(ExtraKeyConstans.NAME, userName);args.putInt(ExtraKeyConstans.AGE, userAge);Log.d(TAG, "-->newInstance(String userName=" + userName + ", int userAge=" + userAge + ")--");return newInstance(args);}public static DetailFragment newInstance(Bundle args) {DetailFragment fragment = new DetailFragment();fragment.setArguments(args);Log.d(TAG, "-->newInstance(Bundle args=" + args + ")--");return fragment;}@Overridepublic void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);Bundle args = getArguments();if (args != null) {userName = args.getString(ExtraKeyConstans.NAME);userAge = args.getInt(ExtraKeyConstans.AGE);}Log.d(TAG, "-->onCreate()--userName=" + userName + ",userAge=" + userAge);}@Nullable@Overridepublic View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {return inflater.inflate(R.layout.fragment_detail, container, false);}
}
    private Bundle mExtras;public @NonNull Intent putExtra(String name, String value) {if (mExtras == null) {mExtras = new Bundle();}mExtras.putString(name, value);return this;}public String getStringExtra(String name) {return mExtras == null ? null : mExtras.getString(name);}public @NonNull Intent putExtras(@NonNull Bundle extras) {if (mExtras == null) {mExtras = new Bundle();}mExtras.putAll(extras);return this;}public @Nullable Bundle getExtras() {return (mExtras != null)? new Bundle(mExtras): null;}

存取数据均跟Bundle 类型的mExtras有关,声明与方法如下:

/*** A mapping from String keys to various {@link Parcelable} values.** @see PersistableBundle*/
public final class Bundle extends BaseBundle implements Cloneable, Parcelable
    public void putString(@Nullable String key, @Nullable String value) {unparcel();mMap.put(key, value);}public String getString(@Nullable String key) {unparcel();final Object o = mMap.get(key);try {return (String) o;} catch (ClassCastException e) {typeWarning(key, o, "String", e);return null;}}

而在Bundle中,数据存取跟ArrayMap<String,Object> mMap有关,所以,最终数据存取都跟这个mMap相关。

ArrayMap是Android平台提供的一个与HashMap功能类似的容器类,声明如下:

package android.util;public final class ArrayMap<K, V> implements Map<K, V>{int[] mHashes;//an integer array of hash codes for each itemObject[] mArray;//an Object array of the key/value pairs.....
}

其内部有两个数组:int[] mHashes; Object[] mArray;

int[] mHashes:contains the hashes of the given keys in sorted order.

Object[] mArray:stores key/value pairs according to the ordering of the "mHashes" array.

其中put和get方法如下:

    /*** Retrieve a value from the array.* @param key The key of the value to retrieve.* @return Returns the value associated with the given key,* or null if there is no such key.*/@Overridepublic V get(Object key) {final int index = indexOfKey(key);return index >= 0 ? (V)mArray[(index<<1)+1] : null;}/*** Add a new value to the array map.* @param key The key under which to store the value.  If* this key already exists in the array, its value will be replaced.* @param value The value to store for the given key.* @return Returns the old value that was stored for the given key, or null if there* was no such key.*/@Overridepublic V put(K key, V value) {final int hash;int index;if (key == null) {hash = 0;index = indexOfNull();} else {hash = mIdentityHashCode ? System.identityHashCode(key) : key.hashCode();index = indexOf(key, hash);}//key已经存在,则直接修改mArray中相应位置的值,并返回旧值。if (index >= 0) {index = (index<<1) + 1;final V old = (V)mArray[index];mArray[index] = value;return old;}//key不存在,根据indexOf返回的位置,将该key对应的hash存入mHashes并将key/values存入mArray中。index = ~index;if (mSize >= mHashes.length) {final int n = mSize >= (BASE_SIZE*2) ? (mSize+(mSize>>1)): (mSize >= BASE_SIZE ? (BASE_SIZE*2) : BASE_SIZE);if (DEBUG) Log.d(TAG, "put: grow from " + mHashes.length + " to " + n);final int[] ohashes = mHashes;final Object[] oarray = mArray;allocArrays(n);if (mHashes.length > 0) {if (DEBUG) Log.d(TAG, "put: copy 0-" + mSize + " to 0");System.arraycopy(ohashes, 0, mHashes, 0, ohashes.length);System.arraycopy(oarray, 0, mArray, 0, oarray.length);}freeArrays(ohashes, oarray, mSize);}if (index < mSize) {if (DEBUG) Log.d(TAG, "put: move " + index + "-" + (mSize-index)+ " to " + (index+1));System.arraycopy(mHashes, index, mHashes, index + 1, mSize - index);System.arraycopy(mArray, index << 1, mArray, (index + 1) << 1, (mSize - index) << 1);}mHashes[index] = hash;mArray[index<<1] = key;mArray[(index<<1)+1] = value;mSize++;return null;}/*** Returns the index of a key in the set.** @param key The key to search for.* @return Returns the index of the key if it exists, else a negative integer.*/public int indexOfKey(Object key) {return key == null ? indexOfNull(): indexOf(key, mIdentityHashCode ? System.identityHashCode(key) : key.hashCode());}int indexOf(Object key, int hash) {final int N = mSize;// Important fast case: if nothing is in here, nothing to look for.if (N == 0) {return ~0;}//根据key的hash值在mHashes里进行二分查找int index = ContainerHelpers.binarySearch(mHashes, N, hash);// If the hash code wasn't found, then we have no entry for this key.if (index < 0) {return index;}//mArray[index*2]存储的值与要查找的key相等,则返回该位置,//否则,则表示发生了冲突。// If the key at the returned index matches, that's what we want.if (key.equals(mArray[index<<1])) {return index;}//发生冲突后,则正序遍历mHashes的(index,N)部分,//如果某个位置存储的值与hash值相等并且mArray中相应位置与要查找的key相等,则返回该位置。// Search for a matching key after the index.int end;for (end = index + 1; end < N && mHashes[end] == hash; end++) {if (key.equals(mArray[end << 1])) return end;}//再逆序遍历mHashes的[0,index)部分。// Search for a matching key before the index.for (int i = index - 1; i >= 0 && mHashes[i] == hash; i--) {if (key.equals(mArray[i << 1])) return i;}// Key not found -- return negative value indicating where a// new entry for this key should go.  We use the end of the// hash chain to reduce the number of array entries that will// need to be copied when inserting.return ~end;}

此外,在put操作时可能会进行相应的扩容操作,而在remove操作中可能会进行相应的缩容操作,这些操作可以减少内存的占用量以提高内存利用率。

由于其采用二分查找在数组上进行插入/删除操作,并且在增/删操作时可能会扩容/缩容操作(重新分配一个新的数组,并将原有数据复制进行),所以对于增/删操作频繁的场景不宜采用ArrayMap。

<1>ArrayMap is a generic key->value mapping data structure that is designed to be more memory efficient than a traditional java.util.HashMap.

<2>Note that this implementation is not intended to be appropriate for data structures that may contain large numbers of items.

<3>For better balance memory use,it will shrink its array as items are removed from it.

综上:

在Activity间或者Activity与Fragment间传递数据,数据量一般很小,并且大部分操作是读取操作(增/删操作较少)所以采用ArrayMap更合适。

github地址:https://github.com/cxcbupt/FullscreenDemo

Refence:

Fun with ArrayMaps (Android Performance Patterns Season 3 ep1)

Android Bundle--ArrayMap详解相关推荐

  1. 【Google Play】App Bundle 使用详解 ( 应用模块化 )

    Google Play 上架完整流程 系列文章目录 [Google Play]创建 Google 开发者账号 ( 注册邮箱账号 | 创建开发者账号 ) [Google Play]创建并设置应用 ( 访 ...

  2. 【Google Play】App Bundle 使用详解 ( 简介 | 应用内更新 | 即时更新 | 灵活更新 )

    Google Play 上架完整流程 系列文章目录 [Google Play]创建 Google 开发者账号 ( 注册邮箱账号 | 创建开发者账号 ) [Google Play]创建并设置应用 ( 访 ...

  3. Android LiveData组件详解以及LiveDataBus

    转载请标明出处:https://blog.csdn.net/zhaoyanjun6/article/details/99749323 本文出自[赵彦军的博客] 一.LiveData简介 LiveDat ...

  4. Android 动画框架详解,第 1 部分

    2019独角兽企业重金招聘Python工程师标准>>> Android 平台提供了一套完整的动画框架,使得开发者可以用它来开发各种动画效果,本文将向读者阐述 Android 的动画框 ...

  5. Android之canvas详解

    首先说一下canvas类: Class Overview The Canvas class holds the "draw" calls. To draw something, y ...

  6. 《Android游戏开发详解》一2.2 设置开发机器

    本节书摘来异步社区<Android游戏开发详解>一书中的第2章,第2.2节,作者: [美]Jonathan S. Harbour 译者: 李强 责编: 陈冀康,更多章节内容可以访问云栖社区 ...

  7. android Json解析详解(详细代码)

    android Json解析详解(详细代码)   JSON的定义: 一种轻量级的数据交换格式,具有良好的可读和便于快速编写的特性.业内主流技术为其提供了完整的解决方案(有点类似于正则表达式 ,获得了当 ...

  8. Android AIDL使用详解

    一.概述 AIDL 意思即 Android Interface Definition Language,翻译过来就是Android接口定义语言,是用于定义服务器和客户端通信接口的一种描述语言,可以拿来 ...

  9. Android 传感器开发详解

    Android 传感器开发详解 本文转载自:https://blog.csdn.net/airsaid/article/details/52902299 前言 使用 第一步 第二步 第三步 方向传感器 ...

  10. android开发照相机啊,Android照相机开发详解(一)

    Android相机开发详解(一) Android相机开发详解(一) 请支持原创,尊重原创,转载请注明出处:http://blog.csdn.net/kangweijian(来自kangweijian的 ...

最新文章

  1. 谷歌浏览器中安装JsonView扩展程序
  2. 四大维度全景揭秘阿里巴巴智能对话开发平台
  3. 判断java String中是否有汉字的方法
  4. u-boot之SPL分析
  5. 4. tensorflow2实现抽样分布—卡方分布、F分布、t分布、Beta分布、Gamma分布——python实战
  6. 拓端tecdat|R语言中的prophet预测时间序列数据模型
  7. 正式环境docker部署hyperf_忍受不了 docker 环境下 hyperf 启动等待时间,教你如何通过 win10 子系统快速运行 hyperf...
  8. Spring Batch之Job级拦截器实现(四)
  9. PSAM卡、SAM卡、SIM卡
  10. RGB888转换为RGB565格式
  11. 分享10款效果惊艳的HTML5图片特效
  12. MATLAB并行计算
  13. 黑马程序员----------Java新特性反射 泛型
  14. linux系统新增一块SCSI硬盘并分区挂载到指定目录
  15. 传腾讯计划出售美团全部股权,知情人士辟谣;苹果证实iOS 16要大量推送广告;Linux 6.0-rc1 发布|极客头条
  16. 学习ZARA模式要从老板观念转变开始
  17. linux服务器添加字体(宋体)
  18. 项目管理---第一章 项目管理的概念
  19. (二十四)优秀员工 - 2
  20. 使用iPerf进行网络吞吐量测试

热门文章

  1. python字符串之join
  2. IO-BufferedInputStream
  3. 184使用 Core Image 框架处理照片
  4. WPF Tile=” 变量 UI 双向绑定”x:Class=Problem/
  5. 求职:网站编辑或网页美工(北京)
  6. base64图片保存获取本地路径
  7. vue脚手架引入swiper
  8. left join on 后and 和 where 的区别
  9. mysqldump: Couldn't execute 'SET OPTION SQL_QUOTE_SHOW_CREATE=1'
  10. .NET技术之美-网络编程