SnapHelper实现recycleiview只能滑一页的原理

SnapHelper通过调用attachToRecycleview方法,将recycleview对象传递到封装类SnapHelper里面。

内部调用了Recycleview.addOnScrollListener 和 setOnFlingListener 方法用来监听我们recycleview滑动。

1
2
3
4
5
// Recycleview.java
// onFling用来监听惯性滑动。 这个监听recycleiview只能拥有一份
public abstract static class OnFlingListener {
public abstract boolean onFling(int velocityX, int velocityY);
}
1
2
3
4
5
6
7
8
9
// java
// 当recycleview发生滚动的时候,这个方法会被调用 这个监听recycleview可以拥有很多份
public abstract static class OnScrollListener {
// 当RecyclerView的滚动状态改变时调用的回调方法。
// SCROLL_STATE_IDLE(g) SCROLL_STATE_DRAGGING SCROLL_STATE_SETTLING.
public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState){}
// 每次滚动的时候在x 和 y 轴的移动距离
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy){}
}

反编译

工具准备

在反编译比较大得apk得时候会遇到一些问题:

比如:java.lang.RuntimeException: can not merge I and Z

解决办法:android 反编译出错 can not merge I and Z - lianghe - 博客园 (cnblogs.com) 替换掉lib文件里面的dex-ir-2.0.jar架包。架包下载路径:链接:https://pan.baidu.com/s/1tYKlC6czgNKk6b_zf1j6Yw 提取码:4djc

img1

然后我们需要下载比较新的dex2jar-2.0工具包:

下载链接:Releases · pxb1988/dex2jar (github.com)


以上工具主备好了就可以进行反编译了:Android开发学习总结(六)—— APK反编译 - 孤傲苍狼 - 博客园 (cnblogs.com)

xposed安装

不root手机:

第一步:这里需要在手机装一个虚拟机:下载链接Releases · android-hacker/VirtualXposed (github.com) 直接下载apk进行安装就好了。

第二部:写模块:

  1. 新建一个app工程。在AndroidManifest.xml加入以下信息:
1
2
3
4
5
6
7
8
9
10
11
12
<!--添加表示 这是一个插件-->
<meta-data
android:name="xposedmodule"
android:value="true" />
<!--载入hook模块之后显示得信息-->
<meta-data
android:name="xposeddescription"
android:value="hell xposed" />
<!--规定jar包版本信息-->
<meta-data
android:name="xposedminversion"
android:value="82" />
img-0
  1. 在build.gradle添加xposed得api依赖:

    1
    provided 'de.robv.android.xposed:api:82'
img-0
  1. 新建assets文件,新建文件xposed_init,并写入hook代码得入口文件

    img-0 img-0
  2. 新建hook得入口类 XposedHook

    1
    2
    3
    4
    5
    6
    public class XposdHook implements IXposedHookLoadPackage {
    @Override
    public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) throws Throwable {
    XposedBridge.log("我hook到了代码"+lpparam.packageName);
    }
    }
  3. 完成

    关于xposed得api接口说明网址:XC_MethodHook | Xposed Framework API


root手机:

安装

下载网址:

[OFFICIAL] Xposed for Lollipop/Marshmallow/Nougat/Oreo [v90-beta3, 2018/01/29] | XDA Forums (xda-developers.com)

img-0 img-0

然后等待安装就好。

LiveData

MutableLiveData

这是最常用的,最基本的一个LiveData


MediatorLiveData

继承自MutableLiveData。它可以观察其他的LiveData对象,并对来自它们的OnChanged事件做出反应。用来合并多个LiveData的值,并且统一做出回应。

例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var   liveData1:LiveData = ...;
var liveData2:LiveData = ...;
var liveDataMerger = MediatorLiveData<T>()
liveDataMerger.addSource(liveData1, value -> liveDataMerger.setValue(value));
liveDataMerger.addSource(liveData2, value -> liveDataMerger.setValue(value));
liveDataMerger.addSource(liveData1, new Observer () {
private int count = 1;

@Override public void onChanged(@Nullable Integer s) {
count++;
liveDataMerger.setValue(s);
if (count > 10) {
liveDataMerger.removeSource(liveData1);
}
}
});

CoroutineLiveData

androidx.lifecycle:lifecycle-livedata-ktx:2.3.1

这是一个内部类,我们没法直接使用。使用方法直接通过 liveData() 的方式进行创建。注意:在liveData()创建一个livedata的时候,他的内部block会在livedata为活跃状态下自动触发。然后需要通过emit或者emitSource方式把结果发送出去。

通过名字就可以知道这是一个具有协程属性挂起的livedata,通过它可以发送延迟的数据,并且他也是和生命周期绑定的。因为使用它只能通过 liveData()这个方法创建,我们就来分析这个:

1
2
3
4
5
public fun <T> liveData(
context: CoroutineContext = EmptyCoroutineContext,
timeoutInMs: Long = DEFAULT_TIMEOUT,
@BuilderInference block: suspend LiveDataScope<T>.() -> Unit
): LiveData<T> = CoroutineLiveData(context, timeoutInMs, block)

构建一个LiveData,其中包含在LiveDataScope上执行的给定块产生的值。当返回的LiveData变为活动时,块开始执行。如果在块执行时,LiveData变为非活动状态,它将在timeoutInMs毫秒之后被取消,除非LiveData在该超时之前再次变为活动状态(以优雅地处理活动旋转等情况)。LiveDataScope任何值。从已取消的块发出的将被忽略。取消之后,如果LiveData再次激活,则将从头重新执行该块。如果你愿意的话。

那这个timeoutInMs是怎么起作用的呢。这里看源码:

在CoroutineLiveData类里面的onInactive(非活跃)方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
internal class CoroutineLiveData<T>(
context: CoroutineContext = EmptyCoroutineContext,
timeoutInMs: Long = DEFAULT_TIMEOUT,
block: Block<T>
) : MediatorLiveData<T>() {
private var blockRunner: BlockRunner<T>?

override fun onActive() {
super.onActive()
blockRunner?.maybeRun()
}

// 当livedata处于非活跃状态 会被系统触发
override fun onInactive() {
super.onInactive()
blockRunner?.cancel()
}
}
internal class BlockRunner<T>(
private val liveData: CoroutineLiveData<T>,
private val block: Block<T>,
private val timeoutInMs: Long,
private val scope: CoroutineScope,
private val onDone: () -> Unit
) {
@MainThread
fun cancel() {
if (cancellationJob != null) {
error("Cancel call cannot happen without a maybeRun")
}
cancellationJob = scope.launch(Dispatchers.Main.immediate) {
// 可以看到这里开启了一个协程,他会延迟我们设定的timeoutInMs时间后在执行,如果5秒内livedata还出去非活跃状态,那么这次事件就执行cancel方法。
delay(timeoutInMs)
if (!liveData.hasActiveObservers()) {
runningJob?.cancel()
runningJob = null
}
}
}
}

案例:

1
2
3
4
val data : LiveData<Int> = liveData {
delay(3000)
emit(3)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 一个基于' userId '获取' User '对象并每30秒刷新一次的LiveData
// as long as it is observed
val userId : LiveData<String> = ...
val user = userId.switchMap { id ->
liveData {
while(true) {
// note that `while(true)` is fine because the `delay(30_000)` below will cooperate in
// cancellation if LiveData is not actively observed anymore
val data = api.fetch(id) // errors are ignored for brevity
emit(data)
delay(30_000)
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// A retrying data fetcher with doubling back-off
val user = liveData {
var backOffTime = 1_000
var succeeded = false
while(!succeeded) {
try {
emit(api.fetch(id))
succeeded = true
} catch(ioError : IOException) {
delay(backOffTime)
backOffTime *= minOf(backOffTime * 2, 60_000)
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// a LiveData that tries to load the `User` from local cache first and then tries to fetch
// from the server and also yields the updated value
val user = liveData {
// dispatch loading first
emit(LOADING(id))
// check local storage
val cached = cache.loadUser(id)
if (cached != null) {
emit(cached)
}
if (cached == null || cached.isStale()) {
val fresh = api.fetch(id) // errors are ignored for brevity
cache.save(fresh)
emit(fresh)
}
}
1
2
3
4
5
6
7
8
9
10
11
// a LiveData that immediately receives a LiveData<User> from the database and yields it as a
// source but also tries to back-fill the database from the server
val user = liveData {
val fromDb: LiveData<User> = roomDatabase.loadUser(id)
emitSource(fromDb)
val updated = api.fetch(id) // errors are ignored for brevity
// Since we are using Room here, updating the database will update the `fromDb` LiveData
// that was obtained above. See Room's documentation for more details.
// https://developer.android.com/training/data-storage/room/accessing-data#query-observable
roomDatabase.insert(updated)
}

LeetCode1-10

1. 有效的括号

给定一个只包括 '('')''{''}''['']' 的字符串,判断字符串是否有效。

有效字符串需满足:

  1. 左括号必须用相同类型的右括号闭合。
  2. 左括号必须以正确的顺序闭合。

解题思路:遍历字符串当符合( { [ 这些字符串的时候就进行压栈,当不等于这些的时候就从栈顶拿一个出来和当前的值进行比较。

答:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
fun main() {
var content = "([]){}"
if(match(content)){
println("符合完美括号")
}else{
println("不符合完美括号")
}
}

fun match(content: String): Boolean {
var stack = Stack<Char>()

for (value in content) {
//如果符合压栈
if (value == '(' || value == '{' || value == '[') {
stack.push(value)
} else {
if(stack.size<=0){
return false
}
var currentValue = stack.pop()
when (currentValue) {
'(' -> {
if (value != ')') {
return false
}
}
'{' -> {
if (value != '}') {
return false
}
}
'[' -> {
if (value != ']') {
return false
}
}
else -> {
return false
}
}
}
}
return stack.size <= 0
}

2. 括号生成

数字n代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且有效的括号组合。

例子:

1
2
输入 n  = 3
输出 ["((()))","(()())","()()()","()(())"]
img1

这里可以发现。每次节点都有两种可能,要么是左括号,要么是右括号。并且还可以发现规律,当右括号的数量大于左括号的数量的时候,是不成立的的。所以咱们可以使用递归:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public class Soulution{
public List<String> getResult(int n){
List<String> result = new ArrayList<String>();
backtracking(n,0,0,result,"");
return result;
}
public void backtracking(int n,int left,int right,List<String> result,String str){
if(right>left){
return;
}
if(left == n && right == n){
result.add(str)
return;
}
if(left < n){
backtracking(n,left+1,right,result,str+"(")
}
if(right < left){
backtracking(n,left,right+1,result,str+"(")
}
}
}

fun main() {
var solution = Solution()
var result = solution.genera(4)
for(value in result){
println(value)
}
}

jetPack-Databind

使用DataBing如果只是想展示数据的话,你的数据类就和常规的一样就好了。如果你想ui监听到你的数据改变的话,你的数据类就需要继承类BaseObservable,参数需要用@Bindable进行声明。

1
2
3
4
class Student : BaseObservable {
@Bindable
var name: String = ""
}

使用@Bindable声明的参数我们在类BR可以找到生成的对应参数名子:

1
2
3
4
public class BR {
public static final int _all = 0;
public static final int name = 1;
}

数据变化我们需要调用notifyPropertyChanged(propertyId) 或者 notifyChange()。一个是指针对某一个id进行更新,一个是针对全部的数据进行更新。

1
2
3
4
5
6
7
8
class Student : BaseObservable {
@Bindable
var name: String = ""
set(value) {
field = value
notifyPropertyChanged(BR.name)
}
}

一台电脑登录多个GitHub方式

  1. 首先生成多个SSH Key(给不同账号配置对应的私钥)
1
ssh-keygen -t ed25519 -C "你的邮箱"
img2

在Ubuntu系统上保存位置: 根目录./ssh

img3
  1. 把 .pub 文件内容 填到github里面:

    1
    2
    // 查看内容
    cat ~/.ssh/id_ed25519.pub
    img1
  2. 把key添加到ssh agent上,由于默认使用的是.ssh/id_rsa,所以你需要显示告诉ssh agent加上新的key

    1
    ssh-add ~/.ssh/id_ed25519

    想要查看的话执行:ssh-add -l

  3. 因为是多账户所以要配置.ssh/config

    一般默认没有config文件,需要手动创建 touch config

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    $ vi .ssh/config

    # 加上以下内容
    #default github
    Host github-A
    HostName github.com
    User git
    IdentityFile ~/.ssh/id_rsa
    IdentitiesOnly yes

    Host github-B
    HostName github.com
    User git
    IdentityFile ~/.ssh/id_rsa_work_two
    IdentitiesOnly yes

    到这里git的配置完成了。

    可以进行远程测试:

    1
    2
    3
    $ ssh –T github-A

    $ ssh –T github-B

    将代码进行上传,这里有一点需要注意,我们远程的写法需要改变。需要填上刚才配置config的HOST的名字:

    原来的写法

    1
    $ git clone git@github.com: 11699/learngit.git

    现在

    1
    $ git clone git@github-B:librityYu/Whatif.git

    还想在完美点可以给仓库设置单独的用户名:

    1
    2
    3
    $ git config user.name "one_name" ; git config user.email "one_email"

    $ git config user.name "two_name" ; git config user.email "two_email"

kotlin代理

委托代理

在kotlin里面代理都是通过by关键字来实现得。代理顾名思义就是重写setValue方法和getValue方法,将某一类型得数据按照我们设计好的某种工厂方式加工出来。比如by lazy,我们希望使用他的代理都可以实现懒加载得功能,帮助开发者省下每次都要写懒加载得方式。

实现代理得思路就是重写setVaule方法和getValue方法。如果是var声明的变量那么就可以重写setValue和getValue。如果是val声明的就只能重写getValue。当然我们还可以自定义提供委托需要重载方法provideDelegate操作符。可以扩展创建属性实现所委托对象的逻辑。

这里先来演示一个简单的,代理getVaule和setValue:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import kotlin.reflect.KProperty

class Delegate {
operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
return "$thisRef, thank you for delegating '${property.name}' to me!"
}

operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
println("$value has been assigned to '${property.name}' in $thisRef.")
}
}

class Example {
var p: String by Delegate()
}
fun main(){
val e = Example()
println(e.p) //Example@33a17727, thank you for delegating ‘p’ to me!
e.p = "NEW" //NEW has been assigned to ‘p’ in Example@33a17727.

}

属性委托要求:

对于val: 委托必须提供一个操作符函数 getValue(),该函数具有以下参数:

  • thisRef —–必须与属性所有者类型(对于扩展属性–指被扩展的类型)相同或者是其超类

  • property—— 必须是类型KProperty<*>` 或其超类型。

1
2
3
4
5
6
7
8
9
class Resource
class Owner {
val valResource: Resource by ResourceDelegate()
}
class ResourceDelegate {
operator fun getValue(thisRef: Owner, property: KProperty<*>): Resource {
return Resource()
}
}

对于var委托必须额外提供一个操作符函数 setValue(), 该函数具有以下参数:

  • thisRef —— 必须与 属性所有者 类型(对于扩展属性——指被扩展的类型)相同或者是其超类型。
  • property —— 必须是类型 KProperty<*> 或其超类型。
  • value — 必须与属性类型相同(或者是其超类型)。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Resource

class Owner {
var varResource: Resource by ResourceDelegate()
}

class ResourceDelegate(private var resource: Resource = Resource()) {
operator fun getValue(thisRef: Owner, property: KProperty<*>): Resource {
return resource
}
operator fun setValue(thisRef: Owner, property: KProperty<*>, value: Any?) {
if (value is Resource) {
resource = value
}
}
}

# 提供委托

provideDelegate 的参数与 getValue 相同:

  • thisRef —— 必须与 属性所有者 类型(对于扩展属性——指被扩展的类型)相同或者是它的超类型;
  • property —— 必须是类型 KProperty<*> 或其超类型。

例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import kotlin.properties.ReadOnlyProperty
import kotlin.reflect.KProperty
class ResourceDelegate<T>(var num:T) : ReadOnlyProperty<MyUI, T> {
override fun getValue(thisRef: MyUI, property: KProperty<*>): T {
return num
}
}

class ResourceLoader<T>(var id: Teacher<T>) {
operator fun provideDelegate(
thisRef: MyUI,
prop: KProperty<*>
): ReadOnlyProperty<MyUI, T> {
checkProperty(thisRef, prop.name)
// 创建委托
return ResourceDelegate(id.tNum)
}

private fun checkProperty(thisRef: MyUI, name: String) {

}
}

class MyUI {
fun <T> bindResource(id: Teacher<T>): ResourceLoader<T> {
return ResourceLoader<T>(id)
}

val image by bindResource(Teacher<Int>(150))
}

fun main(){
var s = MyUI()
System.out.println(s.image)
}

Android重启功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
private fun onLogoutAndRestartApp() {
ActivityManagerUtil.get().finishAllActivity(); //杀死全部activity
var h = Handler(Looper.getMainLooper())
h.postDelayed(Runnable {
restartApp(AppCache.getContext())
Process.killProcess(Process.myPid())
}, 200)
}

private fun restartApp(context: Context) {
val i = context.packageManager.getLaunchIntentForPackage(context.packageName)
i!!.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
context.startActivity(i)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
package com.lin.baselib.util;

import android.Manifest;
import android.app.Activity;
import android.app.Application;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;

import androidx.annotation.RequiresPermission;

import java.lang.ref.WeakReference;
import java.util.Stack;

/**
* @author created by honghengqiang
* @date 2020/10/9 21:14
* email honghengqiang@gmail.com
* description:
*/
public class ActivityManagerUtil {

private static Stack<WeakReference<Activity>> activityStack;
private static ActivityManagerUtil instance;

private ActivityManagerUtil() {
activityStack = new Stack<WeakReference<Activity>>();
}

public static ActivityManagerUtil get() {
synchronized (ActivityManagerUtil.class) {
if (instance == null) {
instance = new ActivityManagerUtil();
}
return instance;
}
}

public void init(Application application) {
application.registerActivityLifecycleCallbacks(new InnerActivityLifecycle());
}

/**
* 获取activity个数
*
* @return
*/
public int size() {
if (activityStack == null) {
activityStack = new Stack<WeakReference<Activity>>();
}
return activityStack.size();
}

/**
* 是否有这个activity(这个activity是否在activity栈内)
*
* @param cls
* @return
*/
public boolean hasActivity(Class<? extends Activity> cls) {
for (int i = 0; i < activityStack.size(); i++) {
if (activityStack.get(i) != null & activityStack.get(i).get() != null && activityStack.get(i).get().getClass().equals(cls)) {
return true;
}
}
return false;
}

/**
* 获取指定的Activity
*/
public static Activity getActivity(Class<? extends Activity> cls) {
WeakReference<Activity> weakReference = findWeakByActivityCls(cls);
if (weakReference != null) {
return weakReference.get();
}
return null;
}

private static WeakReference<Activity> findWeakByActivity(Activity activity) {
for (WeakReference<Activity> weakReference : activityStack) {
if (weakReference.get() != null && weakReference.get() == activity) {
return weakReference;
}
}
return null;
}

private static WeakReference<Activity> findWeakByActivityCls(Class<? extends Activity> activityClass) {
for (WeakReference<Activity> weakReference : activityStack) {
if (weakReference.get() != null && weakReference.get().getClass().equals(activityClass)) {
return weakReference;
}
}
return null;
}

/**
* 获取当前activity
*
* @return
*/
public Activity currentActivity() {
if (!activityStack.isEmpty()) {
WeakReference<Activity> temp = activityStack.lastElement();
if (temp.get() != null) {
return temp.get();
}
}
return null;
}

/**
* 销毁栈顶的activity
*/
public void finishTopActivity() {
WeakReference<Activity> activity = activityStack.lastElement();
if (activity != null && activity.get() != null) {
activity.get().finish();

activityStack.remove(activity);
}
}

/**
* 销毁指定的activity
*
* @param activityClass
*/
public void finishActivity(Class<? extends Activity> activityClass) {
for (int i = 0; i < activityStack.size(); i++) {
WeakReference<Activity> activity = activityStack.elementAt(i);
if (activity != null && activity.get() != null && activity.get().getClass().equals(activityClass)) {
finishActivity(activity.get());
return;
}
}
}

/**
* 销毁指定的activity
*
* @param activity
*/
public void finishActivity(Activity activity) {
if (activity != null) {
WeakReference<Activity> weakReference = findWeakByActivity(activity);
if (weakReference != null) {
if (weakReference.get() != null) {
weakReference.get().finish();
}
activityStack.remove(weakReference);
}
}
}

/**
* 销毁所有activity
*/
public void finishAllActivity() {
if (activityStack == null || activityStack.isEmpty()) {
return;
}
for (WeakReference<Activity> weakReference : activityStack) {
if (weakReference != null && weakReference.get() != null) {
weakReference.get().finish();
}
}
activityStack.clear();
}

/**
* 销毁所有activity,保留最开始的activity
*/
public void popAllActivityKeepTop() {
while (true) {
if (size() <= 1) {
break;
}
Activity activity = currentActivity();
if (activity == null) {
break;
}
finishActivity(activity);
}
}

/**
* 销毁所有activity,保留指定activity
*
* @param cls
*/
public void popAllActivityExceptOne(Class<? extends Activity> cls) {
if (activityStack.isEmpty()) {
return;
}
int i = 0;
while (true) {
int size = activityStack.size();
if (i >= size) {
return;
}
WeakReference<Activity> weakReference = activityStack.get(i);
i++;
if (weakReference == null || weakReference.get() == null) {
i--;
activityStack.remove(weakReference);
continue;
}
if (weakReference.get().getClass().equals(cls)) {
continue;
}
weakReference.get().finish();
activityStack.remove(weakReference);
i--;
}
}

@RequiresPermission(value = Manifest.permission.KILL_BACKGROUND_PROCESSES)
public void quitApp(Context context) {
try {
finishAllActivity();
} catch (Exception e) {
}

// 获取packagemanager的实例
try {
android.app.ActivityManager activityMgr = (android.app.ActivityManager) context
.getSystemService(Context.ACTIVITY_SERVICE);
activityMgr.killBackgroundProcesses(context.getPackageName());
activityStack = null;
instance = null;
} catch (Exception e) {
} finally {
System.exit(0);
}
}

/**
* 添加activity
*
* @param activity
*/
private void pushActivity(Activity activity) {
Log.i("ActivityManager", "当前入栈activity ===>>>" + activity.getClass().getSimpleName());
if (activityStack == null) {
activityStack = new Stack<WeakReference<Activity>>();
}
WeakReference<Activity> item = findWeakByActivity(activity);
if (item == null) {
activityStack.add(new WeakReference<Activity>(activity));
}
}

/**
* 移除activity, 但是不销毁
*
* @param activity
*/
private void removeActivity(Activity activity) {
Log.i("ActivityManager", "当前出栈activity ===>>>" + activity.getClass().getSimpleName());
for (WeakReference<Activity> weakReference : activityStack) {
if (weakReference != null && weakReference.get() != null && weakReference.get() == activity) {
activityStack.remove(weakReference);
return;
}
}
}

private class InnerActivityLifecycle implements Application.ActivityLifecycleCallbacks {

@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
pushActivity(activity);
}

@Override
public void onActivityStarted(Activity activity) {

}

@Override
public void onActivityResumed(Activity activity) {

}

@Override
public void onActivityPaused(Activity activity) {

}

@Override
public void onActivityStopped(Activity activity) {

}

@Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {

}

@Override
public void onActivityDestroyed(Activity activity) {
removeActivity(activity);
}
}

}