Skip to content

Commit 7589bb6

Browse files
author
zhangyang06
committed
[feat] startup 组件开发
1 parent 303bf6c commit 7589bb6

File tree

61 files changed

+1383
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

61 files changed

+1383
-0
lines changed

.idea/.gitignore

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/compiler.xml

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/jarRepositories.xml

Lines changed: 40 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/misc.xml

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

README-ch.md

Whitespace-only changes.

android-startup/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/build

android-startup/build.gradle

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
apply plugin: 'com.android.library'
2+
apply plugin: 'kotlin-android'
3+
4+
android {
5+
compileSdkVersion 30
6+
7+
defaultConfig {
8+
minSdkVersion 21
9+
targetSdkVersion 30
10+
versionCode 1
11+
versionName "1.0"
12+
13+
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
14+
}
15+
16+
17+
buildTypes {
18+
release {
19+
minifyEnabled false
20+
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
21+
}
22+
}
23+
}
24+
25+
dependencies {
26+
implementation fileTree(dir: "libs", include: ["*.jar"])
27+
28+
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
29+
30+
implementation 'androidx.core:core-ktx:1.6.0'
31+
implementation 'androidx.appcompat:appcompat:1.3.1'
32+
testImplementation 'junit:junit:4.+'
33+
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
34+
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
35+
}

android-startup/consumer-rules.pro

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
2+
-keep public class * extends com.rousetime.android_startup.AndroidStartup { *; }
3+
-keep class * implements com.rousetime.android_startup.provider.StartupProviderConfig { *; }

android-startup/proguard-rules.pro

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Add project specific ProGuard rules here.
2+
# You can control the set of applied configuration files using the
3+
# proguardFiles setting in build.gradle.
4+
#
5+
# For more details, see
6+
# http://developer.android.com/guide/developing/tools/proguard.html
7+
8+
# If your project uses WebView with JS, uncomment the following
9+
# and specify the fully qualified class name to the JavaScript interface
10+
# class:
11+
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12+
# public *;
13+
#}
14+
15+
# Uncomment this to preserve the line number information for
16+
# debugging stack traces.
17+
#-keepattributes SourceFile,LineNumberTable
18+
19+
# If you keep the line number information, uncomment this to
20+
# hide the original source file name.
21+
#-renamesourcefileattribute SourceFile
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package com.rousetime.android_startup
2+
3+
import androidx.test.platform.app.InstrumentationRegistry
4+
import androidx.test.ext.junit.runners.AndroidJUnit4
5+
6+
import org.junit.Test
7+
import org.junit.runner.RunWith
8+
9+
import org.junit.Assert.*
10+
11+
/**
12+
* Instrumented test, which will execute on an Android device.
13+
*
14+
* See [testing documentation](http://d.android.com/tools/testing).
15+
*/
16+
@RunWith(AndroidJUnit4::class)
17+
class ExampleInstrumentedTest {
18+
@Test
19+
fun useAppContext() {
20+
// Context of the app under test.
21+
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
22+
assertEquals("com.rousetime.android_startup.test", appContext.packageName)
23+
}
24+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
2+
package="com.rousetime.android_startup">
3+
4+
/
5+
</manifest>
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package com.kronos.lib.startup
2+
3+
/**
4+
* @author : windfall
5+
* @date : 2021/6/16
6+
7+
*/
8+
abstract class SimpleStartupTask : StartupTask {
9+
10+
override fun mainThread(): Boolean {
11+
return true
12+
}
13+
14+
override fun await(): Boolean {
15+
return false
16+
}
17+
18+
19+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package com.kronos.lib.startup
2+
3+
import android.app.Application
4+
import android.content.Context
5+
6+
/**
7+
*
8+
* @Author LiABao
9+
* @Since 2021/9/3
10+
*
11+
*/
12+
13+
14+
fun startUp(context: Application, invoke: Startup.Builder.() -> Unit): Startup.Builder =
15+
Startup.newBuilder().attach(context).apply(invoke)
16+
17+
18+
fun Startup.Builder.insertTask(name: String, runnable: (Context) -> Unit) =
19+
run { addTask(simpleTask(name, runnable)) }
20+
21+
fun Startup.Builder.insertTask(runnable: (Context) -> Unit) =
22+
run { addTask(simpleTask(runnable)) }
23+
24+
25+
fun Startup.Builder.insertTask(runnable: (Context) -> Unit, builder: TaskBuilder.() -> Unit) =
26+
run { addTask(task(runnable, builder)) }
27+
28+
29+
fun simpleTask(name: String, runnable: (Context) -> Unit) =
30+
TaskBuilder(runnable).apply { tag = name }.build()
31+
32+
fun simpleTask(runnable: (Context) -> Unit) =
33+
TaskBuilder(runnable).build()
34+
35+
fun task(runnable: (Context) -> Unit, builder: TaskBuilder.() -> Unit = {}) =
36+
TaskBuilder(runnable).apply(builder).build()
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package com.kronos.lib.startup
2+
3+
import android.app.Application
4+
import java.util.*
5+
6+
/**
7+
* @author : windfall
8+
* @date : 2021/6/16
9+
10+
*/
11+
12+
internal const val TAG = "Startup"
13+
14+
class Startup private constructor(private val builder: Builder) {
15+
16+
private val manager = StartupTaskManager()
17+
18+
companion object {
19+
@JvmStatic
20+
fun newBuilder(): Builder {
21+
return Builder()
22+
}
23+
}
24+
25+
26+
class Builder {
27+
val tasks: MutableList<StartupTask> = ArrayList()
28+
var app: Application? = null
29+
30+
fun attach(app: Application): Builder {
31+
this.app = app
32+
return this
33+
}
34+
35+
fun addTask(task: StartupTask): Builder {
36+
if (!tasks.contains(task)) {
37+
tasks.add(task)
38+
}
39+
return this
40+
}
41+
42+
fun addTaskGroup(group: StartupTaskGroup): Builder {
43+
val taskList = group.group()?.takeIf { it.isNotEmpty() } ?: return this
44+
taskList.forEach {
45+
if (!tasks.contains(it)) {
46+
tasks.add(it)
47+
}
48+
}
49+
return this
50+
}
51+
52+
fun build(): Startup {
53+
return Startup(this)
54+
}
55+
}
56+
57+
fun start() {
58+
if (builder.app == null) {
59+
return
60+
}
61+
manager.start(builder.app!!.applicationContext, builder.tasks)
62+
}
63+
64+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package com.kronos.lib.startup
2+
3+
import android.content.Context
4+
import android.os.SystemClock
5+
import android.util.Log
6+
import java.util.concurrent.Executors
7+
8+
/**
9+
* @author : windfall
10+
* @date : 2021/6/16
11+
12+
*/
13+
internal class StartupDispatcher {
14+
15+
private val executor = Executors.newFixedThreadPool(2)
16+
17+
fun dispatch(
18+
context: Context,
19+
task: StartupTask,
20+
onCompleted: ((task: StartupTask) -> Unit)? = null
21+
) {
22+
if (task.mainThread()) {
23+
execute(context, task)
24+
onCompleted?.invoke(task)
25+
} else {
26+
executor.execute {
27+
execute(context, task)
28+
onCompleted?.invoke(task)
29+
}
30+
}
31+
}
32+
33+
private fun execute(context: Context, task: StartupTask) {
34+
task.onTaskStart()
35+
log(task, "task start.")
36+
val start = SystemClock.elapsedRealtime()
37+
task.run(context)
38+
task.onTaskCompleted()
39+
val duration = SystemClock.elapsedRealtime() - start
40+
val tag = task.tag()?.takeIf { it.isNotBlank() } ?: task.javaClass.simpleName
41+
Log.i(COAST_TAG, "$tag: task completed. cost: ${duration}ms")
42+
log(task, "task completed. cost: ${duration}ms")
43+
track(task, duration)
44+
45+
}
46+
47+
companion object {
48+
private const val COAST_TAG = "Startup.Coast"
49+
}
50+
}
51+
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package com.kronos.lib.startup
2+
3+
import android.content.Context
4+
5+
/**
6+
* @author : windfall
7+
* @date : 2021/6/16
8+
9+
*/
10+
interface StartupTask {
11+
12+
fun run(context: Context)
13+
14+
fun mainThread(): Boolean
15+
16+
fun await(): Boolean
17+
18+
/* 依赖的tag*/
19+
fun dependencies(): List<String> = emptyList()
20+
21+
fun tag(): String
22+
23+
fun onTaskStart(): () -> Unit = {}
24+
25+
fun onTaskCompleted(): () -> Unit = {}
26+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package com.kronos.lib.startup
2+
3+
/**
4+
* @author : windfall
5+
* @date : 2021/6/16
6+
7+
*/
8+
open class StartupTaskGroup {
9+
10+
fun group(): List<StartupTask>? {
11+
return null
12+
}
13+
}

0 commit comments

Comments
 (0)