日期:
来源:鸿洋收集编辑:唐子玄
本文作者
作者:唐子玄
链接:
https://juejin.cn/post/7165427212911378445
本文由作者授权发布。
不同界面之间参数透传。 同一界面中不同层级控件间透传。
// xxxActivity.java
private void parseIntent() {
Bundle paramsCtrl = getIntent().getBundleExtra(RouterConstant.ROUTER_PARAM_CONTROL);
if (paramsCtrl != null) {
mMaxFootageNumber = paramsCtrl.getInt(MaterialConfig.ARG_MATERIAL_MAX_FOOTAGE_NUMBER, -1);
minRangeDuration = paramsCtrl.getLong(MaterialConfig.ARG_KEY_MATERIAL_MIN_DURATION, 0);
maxRangeDuration = paramsCtrl.getLong(MaterialConfig.ARG_KEY_MATERIAL_MAX_DURATION, Long.MAX_VALUE);
shearClipCapacityOn = paramsCtrl.getBoolean(MaterialConfig.ARG_KEY_SHEAR_CAPACITY_ON, true);
mRouterFrom = paramsCtrl.getInt(MaterialProtocol.MATERIAL_SOURCE_KEY, MaterialProtocol.SOURCE.UNKNOWN);
mTemplateFrom = paramsCtrl.getInt(VideoTemplateConfig.KEY_TEMPLATE_SOURCE, VideoTemplateConfig.SOURCE.UNKNOWN);
mCategoryId = paramsCtrl.getString(VideoTemplateConfig.ARG_MATERIAL_TEMPLATE_TAB_ID, "");
mCategoryName = paramsCtrl.getString(VideoTemplateConfig.ARG_MATERIAL_TEMPLATE_TAB_NAME, "");
mTemplateTrace = paramsCtrl.getInt(VideoTemplateConfig.KEY_TEMPLATE_TRACE, VideoTemplateConfig.SOURCE.UNKNOWN);
mTemplatesTraceV2 = paramsCtrl.getInt(VideoTemplateConfig.KEY_TEMPLATES_TRACE_V2, VideoTemplateConfig.TemplatesTraceV2.OTHER);
mMaterialFrom = paramsCtrl.getInt(CommonConstant.EFFECTCENTER.TYPE, Integer.MIN_VALUE);
mMaterialItem = (MediaItem) paramsCtrl.getSerializable(MaterialConfig.EXTRA_KEY_MATERIAL_FILE_PATH);
mDefaultTabIndex = paramsCtrl.getInt(MaterialConfig.EXTRA_KEY_MATERIAL_INDEX, 0);
mDefaultSubTabIndex = paramsCtrl.getInt(MaterialConfig.EXTRA_KEY_MATERIAL_SUB_INDEX, 0);
mShowFolderTab = paramsCtrl.getBoolean(MaterialConfig.ARG_MATERIAL_SHOW_FOLDER_TAB, true);
mShowBottomArea = paramsCtrl.getBoolean(MaterialConfig.ARG_MATERIAL_SHOW_BOTTOM_AREA, true);
mMultiSelectMode = paramsCtrl.getBoolean(MaterialConfig.ARG_MATERIAL_SELECT_MULTI_MODE, true);
mMaterialRemoteMode = paramsCtrl.getInt(MaterialConfig.ARG_MATERIAL_REMOTE_MODE, MaterialRemoteMode.HORIZONTAL);
mClipDuration = paramsCtrl.getLong(MaterialConfig.ARG_MATERIAL_CLIP_DURATION, 0L);
mShowCurrentProjectTab = paramsCtrl.getBoolean(MaterialConfig.ARG_MATERIAL_SHOW_CURRENT_PROJECT_TAB, true);
mFootageConstraintList = (List<MediaItem>) paramsCtrl.getSerializable(MaterialConfig.ARG_MATERIAL_FOOTAGE_CONSTRAINT_LIST);
mFootageDuration = paramsCtrl.getLong(MaterialConfig.ARG_MATERIAL_FOOTAGE_DURATION, 0L);
mMinFootageNumber = paramsCtrl.getInt(MaterialConfig.ARG_MATERIAL_MIN_FOOTAGE_NUMBER, -1);
mVideoTemplateMusicInfo = (VideoTemplateMusicBean) paramsCtrl.getSerializable(VideoTemplateConfig.ARG_MATERIAL_MUSIC_INFO);
mVideoTemplateMusicList = (VideoTemplateMusicBean[]) paramsCtrl.getSerializable(VideoTemplateConfig.ARG_MATERIAL_MUSIC_LIST);
mVideoTemplateId = paramsCtrl.getLong(VideoTemplateConfig.ARG_VIDEO_TEMPLATE_ID);
hasPlayStyleId = paramsCtrl.getBoolean("hasPlayStyleId");
catId = paramsCtrl.getLong(MaterialConfig.EXTRA_TUWEN_CAT_ID);
catTemplateId = paramsCtrl.getLong(MaterialConfig.EXTRA_TUWEN_TEMPLATE_ID);
mVideoTemplatePath = paramsCtrl.getString(VideoTemplateConfig.ARG_VIDEO_TEMPLATE_PATH);
mVideoTemplateDraftId = paramsCtrl.getString(VideoTemplateConfig.ARG_VIDEO_TEMPLATE_DRAFT_ID, "");
mVideoTemplateDownloadUrl = paramsCtrl.getString(VideoTemplateConfig.ARG_VIDEO_TEMPLATE_DOWNLOAD_URL);
mVideoTemplateUpFrom = paramsCtrl.getInt(VideoTemplateConfig.ARG_TEMPLATE_UP_FROM, -1);
mTemplatesUpFromV2 = VideoTemplateConfig.mapTemplatesUpFrom(mVideoTemplateUpFrom);
mExpGrp = paramsCtrl.getString(VideoTemplateConfig.ARG_TEMPLATE_EXP_GRP, "");
mTemplateEnterFrom = paramsCtrl.getString(VideoTemplateConfig.ARG_TEMPLATE_ENTER_FROM, "");
mSceneName = paramsCtrl.getString(StudioReportConstants.ORIGINAL_OPEN_FROM, "");
mTemplateType = paramsCtrl.getInt(VideoTemplateConfig.ARG_MATERIAL_TEMPLATE_TYPE, VideoTemplateConfig.TYPE.TEMPLATE_UNKNOW);
mIsTemplateSupportMatting = paramsCtrl.getBoolean(VideoTemplateConfig.ARG_MATERIAL_TEMPLATE_SUPPORT_MATTING, false);
mIsTemplateSupportBlink = paramsCtrl.getBoolean(MaterialConfig.ARG_MATERIAL_SUPPORT_BLINK, false);
isSearch = paramsCtrl.getString(MaterialConfig.EXTRA_IS_SEARCH, "0");
...
}
}
// xxxActivity.java
private void goNext(Long materialDraftId, boolean isRoughShear) {
final Intent intent = new Intent();
intent.putExtra(MaterialProtocol.MATERIAL_SOURCE_KEY, mRouterFrom);
intent.putExtra(VideoTemplateConfig.KEY_TEMPLATE_SOURCE, mTemplateFrom);
intent.putExtra(VideoTemplateConfig.KEY_TEMPLATE_TRACE, mTemplateTrace);
intent.putExtra(VideoTemplateConfig.ARG_MATERIAL_TEMPLATE_TAB_NAME, mCategoryName);
intent.putExtra(VideoTemplateConfig.ARG_MATERIAL_TEMPLATE_TAB_ID, mCategoryId);
intent.putExtra(VideoTemplateConfig.KEY_TEMPLATES_TRACE_V2, mTemplatesTraceV2);
intent.putExtra(MaterialConfig.ARG_MATERIAL_SHOW_CURRENT_PROJECT_TAB, mShowCurrentProjectTab);
intent.putExtra(VideoTemplateConfig.ARG_VIDEO_TEMPLATE_ID, mVideoTemplateId);
intent.putExtra(VideoTemplateConfig.ARG_VIDEO_TEMPLATE_PATH, mVideoTemplatePath);
intent.putExtra(VideoTemplateConfig.ARG_MATERIAL_MUSIC_INFO, mVideoTemplateMusicInfo);
intent.putExtra(VideoTemplateConfig.ARG_MATERIAL_MUSIC_LIST, mVideoTemplateMusicList);
intent.putExtra(VideoTemplateConfig.ARG_TEMPLATE_UP_FROM, mVideoTemplateUpFrom);
intent.putExtra(VideoTemplateConfig.ARG_TEMPLATE_EXP_GRP, mExpGrp);
intent.putExtra(VideoTemplateConfig.ARG_TEMPLATE_ENTER_FROM, mTemplateEnterFrom);
intent.putExtra(StudioReportConstants.ORIGINAL_OPEN_FROM, mSceneName);
intent.putExtra(StudioReportConstants.EXTRA_KEY_MATERIAL_DRAFT_ID, materialDraftId);
intent.putExtra(VideoTemplateConfig.ARG_MATERIAL_TEMPLATE_TYPE, mTemplateType);
intent.putExtra(MaterialConfig.EXTRA_IS_SEARCH, isSearch);
...
}
最绝望的是,当新增一个 Activity 时,你发现它要的一个数据在跳转链路上往前数第 4 个 Activity。这意味着你得在5个 Activity 中声明4个成员变量,调用4次put方法,以及4次get方法,才能获取想要的值。
// android.app.Activity.java
public void startActivity(Intent intent) {
this.startActivity(intent, null);
}
// android.content.Intent.java
public @NonNull Intent putExtra(String name, @Nullable Bundle value) {
if (mExtras == null) {
mExtras = new Bundle();
}
mExtras.putBundle(name, value);
return this;
}
// android.content.Intent.java
public @Nullable Bundle getBundleExtra(String name) {
return mExtras == null ? null : mExtras.getBundle(name);
}
interface Param {
val paramMap: Map<String, Any>
}
class Activity1 : AppCompatActivity(), Param{
override val paramMap: Map<String, Any>
get() = mapOf( "type" to 1 )
}
class Activity1 : AppCompatActivity(), Param{
private var materialType:Int = 0
override val paramMap: Map<String, Any>
get() = mapOf( "type" to materialType )
}
fun <T> Activity.getParam(key: String): T {}
val ams = getSystemService(Context.ACCESSIBILITY_SERVICE) as ActivityManager
val tasks = ams.getRunningTasks(10)
val iterator = tasks.iterator()
while (iterator.hasNext()){
val taskInfo = iterator.next() as RunningTaskInfo
taskInfo.topActivity
}
object PageStack : Application.ActivityLifecycleCallbacks {
val stack = LinkedList<Activity>()
override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
stack.add(activity)
}
override fun onActivityDestroyed(activity: Activity) {
stack.remove(activity)
}
override fun onActivityStarted(activity: Activity) {}
override fun onActivityResumed(activity: Activity) {}
override fun onActivityPaused(activity: Activity) {}
override fun onActivityStopped(activity: Activity) {}
override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {}
}
class MyApplication : Application() {
override fun onCreate() {
super.onCreate()
registerActivityLifecycleCallbacks(PageStack)
}
}
fun <T> Activity.getParam(key: String): T {
// 获取 Activity 栈的迭代器
val iterator = PageStack.stack.let { it.listIterator(it.size) }
// 从后往前迭代
while (iterator.hasPrevious()) {
// 获取上一个 Activity 结点
val activity = iterator.previous()
// 如果 Activity 携带参数,则根据 key 获取参数
(activity as? Param)?.paramMap?.getOrDefault(key, null)?.also { return it as
}
throw IllegalArgumentException("missing Parameter for the previous Activity/Fragment")
}
class Activity1 : AppCompatActivity(), Param{
private var materialType:Int = 0
// 定义当前 Activity 能生成的参数
override val paramMap: Map<String, Any>
get() = mapOf( "type" to materialType )
}
class Activity3 : AppCompatActivity(){
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
getParam<Int>("type") // 获取 Activity1 的参数
}
}
class Fragment1:Fragment(), Param{
private var materialType:Int = 0
override val paramMap: Map<String, Any>
get() = mapOf( "type" to materialType )
}
object PageStack : Application.ActivityLifecycleCallbacks {
val stack = LinkedList<Activity>()
// Fragment 集合
val fragments = hashMapOf<Activity, MutableList<Fragment>>()
// Fragment 生命周期监听器
private val fragmentLifecycleCallbacks by lazy(LazyThreadSafetyMode.NONE) {
object : FragmentManager.FragmentLifecycleCallbacks() {
override fun onFragmentViewCreated(fm: FragmentManager, f: Fragment, v: View, savedInstanceState: Bundle?) {
// 当 Fragment 被创建后,把它和相关的 activity 存入 map
f.activity?.also { activity ->
fragments[activity]?.also { it.add(f) } ?: run { fragments[activity] = mutableListOf(f) }
}
}
}
}
override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
stack.add(activity)
// 注册 Fragment 生命周期监听器
(activity as? FragmentActivity)?.supportFragmentManager?.registerFragmentLifecycleCallbacks(fragmentLifecycleCallbacks, true)
}
override fun onActivityDestroyed(activity: Activity) {
stack.remove(activity)
// 移除 Fragment 生命周期监听器
(activity as? FragmentActivity)?.supportFragmentManager?.unregisterFragmentLifecycleCallbacks(fragmentLifecycleCallbacks)
// 清空 Fragment 集合
fragments[activity]?.clear()
fragments.remove(activity)
}
override fun onActivityStarted(activity: Activity) {}
override fun onActivityResumed(activity: Activity) {}
override fun onActivityPaused(activity: Activity) {}
override fun onActivityStopped(activity: Activity) {}
override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {}
}
fun <T> Activity.getParam(key: String): T {
val iterator = PageStack.stack.let { it.listIterator(it.size) }
while (iterator.hasPrevious()) {
val activity = iterator.previous()
// 先查询 Activity 层级是否存在参数
(activity as? Param)?.paramMap?.getOrDefault(key, null)?.also { return it as T }
// 若 Activity 层级查询失败,继续查询该页面的所有 Fragment
val paramFragment = PageStack.fragments[activity]?.firstOrNull { (it as? Param)?.paramMap?.getOrDefault(key, null) != null }
if(paramFragment !=null) return (paramFragment as Param).paramMap[key] as T
}
throw IllegalArgumentException("missing Parameter for the previous Activity/Fragment")
}
通过将“显式向后透传参数”转变为“隐式向前查询参数”完全避免了界面间的参数透传,使得各界面间更加耦合,参数更容易维护。
同时通过 Kotlin 的抽象属性,扩展方法,对象声明、类型转换 as? 这些语法糖将向前查询参数的复杂度隐藏起来,使得上层能以最简洁的方式查询参数。
最后推荐一下我做的网站,玩Android: wanandroid.com ,包含详尽的知识体系、好用的工具,还有本公众号文章合集,欢迎体验和收藏!
推荐阅读:
扫一扫 关注我的公众号
如果你想要跟大家分享你的文章,欢迎投稿~
┏(^0^)┛明天见!