如何用反射获取activity实例

如何用反射获取activity实例,第1张

我擦,你这样程序还有安全可言,其他程序可以 *** 作你的Activity,再说Activity里面那么多的回调方法都是框架调用的,你获取到了实例出来有个屁用不过通过PackageManager是可以获取到其他程序的Activity的信息,包括报名,等等

Activity作为安卓四大组件之一,是最重要也是用得最多的组件,涉及的知识点非常多,有些知识点平时开发很少用到,但在某些场景下需要特别注意,本文详细整理了Activity涉及的知识点,供开发参考。

针对Activity可以提出很多问题,如:

Activity 的生命周期

Activity 之间的通信方式?

Activity 各种情况下的生命周期?

横竖屏切换时 Activity 的生命周期?

前台切换到后台,然后再回到前台时 Activity 的生命周期?

d出 Dialog 的时候按 Home 键时 Activity 的生命周期?

两个Activity之间跳转时的生命周期?

下拉状态栏时 Activity 的生命周期?

Activity 与 Fragment 之间生命周期比较?

Activity 的四种 LaunchMode(启动模式)的区别?

Activity 状态保存与恢复?

Activity的转场动画有哪些实现方式?

Activity的生命周期中怎么获取控件宽高?

onNewIntent的执行时机?

如何连续退出多个Activity?

如何把Acitivty设置成Dialog样式 ,android:theme="@android:style/ThemeDialog"

关于横竖屏切换的生命周期,对应不同的手机,由于厂商定制的原因,会有不同的效果,如设置了configChanges="orientation”在有些手机会执行各个生命周期,但有些手机却不会执行。

网上常见的结论如下:

但实际的测试如下:

可以看出,不同厂商的手机切屏生命周期会有差异。

从API 13以上,当设备在横竖切屏时,“屏幕尺寸”也会发生变化,因此为了杜绝切屏导致页面销毁重建,需要加上screenSize,使用设置4,即 android:configChanges="orientation|keyboardHidden|screenSize"

Activity的四种状态如下:

在activity处于paused或者stoped状态下,如果系统内存紧张,可能会被销毁,当重回该activity时会重建,正常返回和被回收后返回的生命周期如下:

如果是回收后返回,onCreate的参数savedInstanceState不为空。

有哪些场景会触发onNewIntent回调呢?跟启动模式有关,首先该Activity实例已经存在,再次启动才可能触发。一种情况是启动模式是singleTask或者singleInstance,无论该activity在栈中哪个位置,都会触发onNewIntent回调,并且把上面其他acitivity移除,另一种情况是启动模式是singleTop或者以FLAG_ACTIVITY_SINGLE_TOP启动,并且该activity实例在栈顶,会触发onNewIntent,如果不在栈顶是重新创建的,不会触发。

在实际业务开发中,往往碰到需要连续退出多个activity实例,下面整理了几种常见方法:

● 发送特定广播

1、在需要处理连续退出的activity注册该特定广播;

2、发起退出的activity发送该特定广播;

3、接收到该广播的activity 调用finish结束页面。

● 递归退出

1、用startActivityForResult启动新的activity;

2、前一个页面finish时,触发onActvityResult回调,再根据requestCode和resultCode处理是否finish,达到递归退出的效果。

● FLAG_ACTIVITY_CLEAR_TOP

通过intentsetFlag(IntentFLAG_ACTIVITY_CLEAR_TOP)启动新activity,如果栈中已经有该实例,则会把该activity之上的所有activity关闭,达到singleTop启动模式的效果。

● 自定义activity栈

1、自定义activity列表,新打开activity则加入栈中,关闭则移除栈;

2、需要退出多个activity时,则循环从栈中移除activity实例,并调用finish。

在讨论Activity启动模式经常提到任务栈,那到底什么是任务栈?

任务是一个Activity的集合,它使用栈的方式来管理其中的Activity,这个栈又被称为返回栈(back stack),栈中Activity的顺序就是按照它们被打开的顺序依次存放的。返回栈是一个典型的后进先出(last in, first out)的数据结构。下图通过时间线的方式非常清晰地向我们展示了多个Activity在返回栈当中的状态变化:

taskAffinity 任务相关性,可以用于指定一个Activity更加愿意依附于哪一个任务,在默认情况下,同一个应用程序中的所有Activity都具有相同的affinity, 名字为应用的包名。当然了,我们可以为每个 Activity 都单独指定 taskAffinity 属性(不与包名相同)。taskAffinity 属性主要和 singleTask 启动模式和 allowTaskReparenting 属性配对使用,在其他情况下没有意义。

taskAffinity 有下面两种应用场景:

分为显示启动和隐式启动。

(1)显示启动

直接指定待调整的Activity类名。

(2)隐式启动

Intent 能够匹配目标组件的 IntentFilter 中所设置的过滤信息,如果不匹配将无法启动目标 Activity。IntentFilter 的过滤信息有 action、category、data。

IntentFilter 需要注意的地方有以下:

● 一个 Activity 中可以有多个 intent-filter

● 一个 intent-filter 同时可以有多个 action、category、data

● 一个 Intent 只要能匹配任何一组 intent-filter 即可启动对应 Activity

● 新建的 Activity 必须加上以下这句,代表能够接收隐式调用

<category android:name="androidintentcategoryDEFAULT" />

只要匹配一个action即可跳转,注意的是action要区分大小写。

规则:如果intent中有category,则所有的都能匹配到intent-filter中的category,intent中的category数量可用少于intent-filter中的。另外,单独设置category是无法匹配activity的,因为category属性是一个执行Action的附加信息。

intent不添加category会匹配默认的,即 “android:intentcategoryDEFAULT”

如果上面例子,如果去掉intentsetAction("action_name"),则会抛出异常:

规则:类似action,但data有复杂的结构,只要匹配一个data并且与data中所有属性都一致就能匹配到Activity,只要有1个属性不匹配,都无法找到activity。

data的结构:

data 主要是由 URI 和 mimeType 组成的。

URI 可配置很多信息,的结构如下:

与url类似,例如:

mineType:指资源类型包括文本、、音视频等等,例如:text/plain、 image/jpeg、video/ 等

下面看下data匹配的例子:

只匹配scheme

只匹配scheme也是能匹配到activity的。

匹配scheme、host、port

将上面的data改为

匹配mineType

如果有mineType,则不能仅设置setData或setMineType了,因为setData会把mineType置为null,而setMineType会把data置为null,导致永远无法匹配到activity,要使用setDataAndType。

使用scheme的默认值content\file

注意该方法需要在startAtivity方法或者是finish方法调用之后立即执行,不能延迟,但可以在子线程执行。

而在windowAnimationStyle中存在四种动画:

activityOpenEnterAnimation // 打开新的Activity并进入新的Activity展示的动画

activityOpenExitAnimation // 打开新的Activity并销毁之前的Activity展示的动画

activityCloseEnterAnimation //关闭当前Activity进入上一个Activity展示的动画

activityCloseExitAnimation // 关闭当前Activity时展示的动画

overridePendingTransition的方式比较生硬,方法也比较老旧了,不适用于MD风格,google提供了新的转场动画ActivityOptions,并提供了兼容包ActivityOptionsCompat。

我们知道在onCreate和onResume里面直接获取到控件宽高为0,那有什么办法获取到控件的实际宽高?只要有onWindowFocusChanged、viewpost、ViewTreeObserver三种方式获取。

当用户点击桌面图标启动APP时,背后的流程如下:

我们看到的手机桌面是Launch程序的界面,点击应用图标会触发点击事件,调用startActivity(intent),然后通过Binder IPC机制,与ActivityManagerService(AMS)通讯,AMS执行一系列 *** 作,最终启动目前应用,大概流程如下:

通过PackageManager的resolveIntent()收集跳转intent对象的指向信息,然后通过grantUriPermissionLocked()方法来验证用户是否有足够的权限去调用该intent对象指向的Activity。如果有权限,则在新的task中启动目标activity,如果发现没有进程,则先创建进程。

如果进程不存在,AMS会调用startProcessLocked创建新的进程,在该方法中,会通过socket的通讯方式通知zygote进程孵化新的进程并返回pid,在新的进程中会初始化ActivityThread,并依次调用LooperprepareLoop()和Looperloop()来开启消息循环。

创建好进程后下一步要将Application和进程绑定起来,AMS会调用上一节创建的ActivityThread对象的bindAppliction方法完成绑定工作,该方法会发送一条BIND_APPLICATION的消息,最终会调用handleBindApplication方法处理消息,并调用makeApplication方法处理消息,加载APP的classes到内存中。

通过前面的步骤,系统已经拥有了该Application的进程,后续的启动则是从已存在其他进程中启动Acitivity,即调用realStartAcitvityLocked,该方法会调用Application的主线程对象ActivityThread的sheduleLaunchActivity方法,在方法中会发送LAUNCH_ACTIVITY到消息队列,最终通过handleLaunchActivity处理消息,完成Acitivty的启动。

Activity

Activity 的 36 大难点,你会几个?「建议收藏」

[译]Android Application启动流程分析

1一般来说,这样做是不好的如果要这样做,说明你的设计存在一定的问题

首先从面向对象设计来说,不应该直接引用其他类的变量,而只应该通过类的方法来完成对类的 *** 作

此外因为Activity生命周期的管理是由android framework来实现的,你难以确切知道MainActivity的状态,无法保证引用变量的有效性

如果一定要这么做,你可以实现一个类似getInstance的静态方法,不过注意不能像单例设计模式那样,new 一个MainActivity,而是在onreate的时机给静态变量instance赋值

   MainActivity 通过 startActivityForResult 启动 MainActivity2 ,同时传递一个 Bundle 对象给 MainActivity2 ,在 MainActivity2 中通过 getIntent 获取到传递过来的 Bundle ,进而得到 MainActivity 传递过来的String 数据并打印。

  在 MainActivity2 中通过 setResult 设置需要传递给 MainActivity 的 Bundle 数据,在 MainActivity 的 onActivityResult 函数中就可以得到相关的 Bundle 数据。

  每一个Android应用都有一个 Application 对象,这个 Application 会贯穿整个Android应用,在其中定义的变量,它的生命周期也是和整个应用的生命周期一样。

  在 MainActivity 中定义了一个 伴生变量 ,它相当于 Java中的静态变量 ,而在 MainActivity2 中可以获取此静态变量,并对其进行修改。

  通过 Fragment 的 setArguments(bundle) 实现 Activity 想 Fragment 传值。

  通过 onAttach(activity: Activity) 方法获得 activity 实例,直接调用 activity 中的方法获得数据。

   Service 的 onBind 方法需要返回一个 Binder 对象,而这个对象在 ServiceConnectiononServiceConnected 中可以获取,从而实现 Service 和 Activity 之间的通信。

   startService 时,传入参数 intent 可以携带部分参数给 Service ,我们可以在 Service 的 onStartCommand 方法中得到 startService 传递过来的 intent 数据。

  在service中持有 callback 接口,并在binder中定义方法得到service的实例。activity中实现 ServiceConnection ,通过绑定启动service,这样会回调 ServiceConnection 接口的 onServiceConnected 方法,从而得到service实例,对service中的 callback 进行赋值,在service中可进行耗时 *** 作并见数据通过callback接口,传递给activity进行其他 *** 作。

除了上面说的常用方法外,还有很多其他方法,比如广播机制,事件总汇(eventbus)等。

在application中可以存放Acitivity_B的实例,并且设置get 和 set 方法,这样,就可以在应用程序中随时从application中获取到Activty_B的实例了。

给它一个静态的方法,一边获取activity的实例,然后在另一个activity中获取,这样就可以了

public class Activity1 {

private Activity1 mActivity1 = null;

public void onCreate(Bundle savedInstanceState) {

mActivity1 = this;

}

public static Activity1 getInstance () {

if (mActivity1 != null) {

return mActivity1;

}

return null;

}

}

public calss Activity2 {

/在这里就可以用上个Activity的方法了/

}

以上就是关于如何用反射获取activity实例全部的内容,包括:如何用反射获取activity实例、Android之Activity全面解析,有些知识点容易忘记、Android 如何在其他类里面获得MainActivity类的实例,从而引用MainActivity类里的变量等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/9463652.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-28
下一篇 2023-04-28

发表评论

登录后才能评论

评论列表(0条)

保存