从0到1打造一款安卓app之6-安卓技术选型(将会持续更新)

从0到1打造一款安卓app之6-安卓技术选型(将会持续更新)

以kotlin为基础

1.jetpack全家桶

Android 架构组件-jetpack全家桶

1.AppStartup

用于应用初始化,初始化时可以访问到context: Context

自定义一个类,继承Initializer

class StartupInitializer :Initializer<String>{
    override fun create(context: Context): String {
        Log.d(StartupInitializer::class.java.simpleName,"create")
        return "test"
    }

    override fun dependencies(): MutableList<Class<out Initializer<*>>> {
        Log.d(StartupInitializer::class.java.simpleName,"dependencies")
        //被依赖的先执行,再执行自定义的StartupInitializer create
        return mutableListOf()
    }
}
复制代码

AndroidManifest.xml里配置StartupInitializer,tools:node="remove"禁用自定义的Initializer自动初始化

<provider
    android:name="androidx.startup.InitializationProvider"
    android:authorities="${applicationId}.androidx-startup"
    android:exported="false"
    tools:node="merge"
    tools:replace="android:authorities" />
<meta-data
    android:name="base.module.android.StartupInitializer"
    android:value="androidx.startup"
    tools:node="remove"/>
复制代码

手动调用自定义的Initializer初始化

val result = AppInitializer.getInstance(this).initializeComponent(StartupInitializer::class.java)
复制代码

2.WorkManager

work组件定义了一个WorkManagerInitializer,WorkManager 会默认初始化

public final class WorkManagerInitializer implements Initializer<WorkManager> {

    private static final String TAG = Logger.tagWithPrefix("WrkMgrInitializer");

    @NonNull
    @Override
    public WorkManager create(@NonNull Context context) {
        // Initialize WorkManager with the default configuration.
        Logger.get().debug(TAG, "Initializing WorkManager with default configuration.");
        WorkManager.initialize(context, new Configuration.Builder().build());
        return WorkManager.getInstance(context);
    }

    @NonNull
    @Override
    public List<Class<? extends androidx.startup.Initializer<?>>> dependencies() {
        return Collections.emptyList();
    }
}
复制代码

Application 实现 Configuration.Provider

import androidx.work.Configuration
class MyApplication() : Application(), Configuration.Provider {
     override fun getWorkManagerConfiguration() =
           Configuration.Builder()
                .setMinimumLoggingLevel(android.util.Log.INFO)
                .build()
}
复制代码

如果不想要work组件自带的WorkManagerInitializer

移除默认的初始化

<provider
    android:name="androidx.startup.InitializationProvider"
    android:authorities="${applicationId}.androidx-startup"
    android:exported="false"
    tools:node="merge"
    tools:replace="android:authorities">
    ...其他自定义的初始化器
    <meta-data
        android:name="androidx.work.WorkManagerInitializer"
        android:value="androidx.startup"
        tools:node="remove" />
</provider>
复制代码

手动添加到自定义的初始化器依赖下

class StartupInitializer : Initializer<String> {
    override fun create(context: Context): String {
        return "test"
    }

    override fun dependencies(): MutableList<Class<out Initializer<*>>> {
        return mutableListOf(
            xxyyzz::class.java,
            WorkManagerInitializer::class.java,
            xxx::class.java,
        )
    }
}
复制代码

3.lifecycle生命周期感知

感知整个application生命周期示例

class ProcessLifecycleObserver :DefaultLifecycleObserver {

    override fun onCreate(owner: LifecycleOwner) {
        super.onCreate(owner)
    }

    override fun onStart(owner: LifecycleOwner) {
        super.onStart(owner)
    }

    override fun onResume(owner: LifecycleOwner) {
        super.onResume(owner)
    }

    override fun onPause(owner: LifecycleOwner) {
        super.onPause(owner)
    }

    override fun onStop(owner: LifecycleOwner) {
        super.onStop(owner)
    }

    override fun onDestroy(owner: LifecycleOwner) {
        super.onDestroy(owner)
    }
}

复制代码
class BaseApplication : Application() {

    override fun onCreate() {
        super.onCreate()
        ProcessLifecycleOwner.get().lifecycle.addObserver(ProcessLifecycleObserver())
    }
}
复制代码

其他示例请查看官网

2.Square公司系列

1. Okhttpt

OkHttp

Okhttp初始化与AppStartUp,因为要访问context: Context

//后面有需要时,直接globalOkHttpClient.newBuilder()创建一个新的build来自定义新的配置
lateinit var globalOkHttpClient: OkHttpClient

class OkHttpClientInitializer : Initializer<OkHttpClient> {
    override fun create(context: Context): OkHttpClient {
        Log.d(
            OkHttpClientInitializer::class.java.simpleName,
            "context.externalCacheDir:${context.externalCacheDir}"
        )
        Log.d(
            OkHttpClientInitializer::class.java.simpleName,
            "context.externalCacheDir exists:${context.externalCacheDir?.exists()}"
        )
        Log.d(
            OkHttpClientInitializer::class.java.simpleName,
            "context.filesDir:${context.filesDir}"
        )

        globalOkHttpClient = OkHttpClient.Builder()
            //配置响应内容缓存
            .cache(
                Cache(
                    directory = context.externalCacheDir ?: context.filesDir,
                    maxSize = 100 * 1024L * 1024L
                )
            )
            //配置超时
            .callTimeout(30, TimeUnit.SECONDS)
            .connectTimeout(30, TimeUnit.SECONDS)
            .readTimeout(30, TimeUnit.SECONDS)
            .writeTimeout(30, TimeUnit.SECONDS)
            //添加默认请求拦截器
            .addInterceptor(HttpLoggingInterceptor())
            .build()
        return globalOkHttpClient
    }

    override fun dependencies(): MutableList<Class<out Initializer<*>>> {
        return mutableListOf()
    }
}
复制代码

2. retrofit

retrofit

//后面使用时,.newBuilder()创建新的Builder,重新自定义一个配置
// globalRetrofit.newBuilder()
//            .baseUrl("https://www.baidu.com/")
//            .build()
//            .create(BaiduService::class.java)

lateinit var globalRetrofit: Retrofit

class RetrofitInitializer : Initializer<Unit> {
    override fun create(context: Context):Unit {
        val moshi = Moshi.Builder().build()
        val gson: Gson = GsonBuilder().create()
        val moshiConverterFactory: MoshiConverterFactory = MoshiConverterFactory.create(moshi)

        globalRetrofit = Retrofit.Builder()
            .baseUrl("https://x.y.z")
            .client(globalOkHttpClient)
            .addConverterFactory(moshiConverterFactory)
            .addConverterFactory(ScalarsConverterFactory.create())
            .build()
    }

    override fun dependencies(): MutableList<Class<out Initializer<*>>> {
        return mutableListOf()
    }
}
复制代码

3.1 retrofit与kotlin协程配合使用

retrofit新版本自带支持kotlin协程,只需要在定义请求时,用suspend修饰fun,即不是普通的fun,而是 suspend fun

@POST("{keyword}")
@Headers("Content-Type: application/json")
suspend fun addData(@Path("keyword") keyword: String, @Body data: String): Any
复制代码

3.2定义一个全局可以使用的协程作用域

val handler = CoroutineExceptionHandler { _, exception ->
    LogUtils.e("CoroutineExceptionHandler", "CoroutineExceptionHandler get: $exception")
}

val mainScope = MainScope()

fun runOnAsyncScope(block: suspend CoroutineScope.() -> Unit) = mainScope.launch(Dispatchers.Default + handler) {
    block.invoke(this)
}
复制代码

3. moshi json解释库

简单使用示使

定义适配器工厂类和JsonAdapter类

import com.squareup.moshi.*
import java.lang.reflect.Type
import java.util.*

@Retention(AnnotationRetention.RUNTIME)
@JsonQualifier
annotation class DateLong

class DateLongJsonAdapterFactory : JsonAdapter.Factory {

    override fun create(type: Type, annotations: MutableSet<out Annotation>, moshi: Moshi): JsonAdapter<*>? {
        if (type != Date::class.java) return null
        Types.nextAnnotations(annotations, DateLong::class.java) ?: return null

        return DateLongAdapter().nullSafe()
    }

    private class DateLongAdapter : JsonAdapter<Date>() {

        override fun fromJson(reader: JsonReader): Date {
            return Date(reader.nextLong())
        }

        override fun toJson(writer: JsonWriter, value: Date?) {
            writer.value(value?.time ?: 0)
        }
    }
}
复制代码

定义数据类,并添加注解

@JsonClass(generateAdapter = true)
open class BaseObject(
    open var createdAt: String = TimeUtils.date2String(Date()),
    open var updatedAt: String = TimeUtils.date2String(Date()),
)

@JsonClass(generateAdapter = true)
data class FinalObject(
    @DateLong var createdAtTime: Date = Date(),
    @DateLong var updatedAtTime: Date = Date(),
) : BaseObject()
复制代码

简单使用

val globalMoshi = Moshi.Builder()
    .add(DateLongJsonAdapterFactory())
    .build()

val adapter = globalMoshi.adapter(FinalObject::class.java)
val str = adapter.toJson(FinalObject())
复制代码

4. leakcanary内存泄漏检测库

引入依赖

dependencies {
  // debugImplementation because LeakCanary should only run in debug builds.
  debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.9.1'
}
复制代码

查看应用日志LeakCanary是否正常工作

D LeakCanary: LeakCanary is running and ready to detect leaks

如果显示 ,则需要处理一下,

[Can't use LeakCanary because of org.junit.Test class dependency in external libraries]
复制代码

LeakCanary is currently disabled: test class org.junit.Test was found in classpath. · Issue #1968 · square/leakcanary · GitHub

//在app主模块下,添加下面三行配置
configurations {
    debugImplementation.exclude group: "junit", module: "junit"
}

dependencies {

}
复制代码

3.腾讯公司

bugly

Android SDK 使用指南 - Bugly 文档 (qq.com)

添加依赖


dependencies {
    implementation 'com.tencent.bugly:crashreport:4.0.4'
}
复制代码

初始化

class CrashReportInitialzer : Initializer<Unit> {

    override fun create(context: Context) {
        CrashReport.initCrashReport(context, "AppId", false)
    }

    override fun dependencies(): MutableList<Class<out Initializer<*>>> {
        return mutableListOf()
    }
}
复制代码

测试

CrashReport.testJavaCrash()

腾讯浏览服务

腾讯浏览服务 (tencent.com)

4.日志记录与工具类

AndroidUtilCode 集成了各种各样的工具类和日志功能,这一个类库可以打日志打印到控制台,也可以把日志/崩溃记录写入到文件,但唯一不足的是,写入到文件的日志,只能是使用类里提供的LogUtils类打印的,系统或者第三方库的Log日志则会记录不到,所以可以使用 (Gradle + ASM)修改字节码的方案。

5.浏览器

腾讯浏览服务 (tencent.com)

AgentWeb

猜你喜欢

转载自juejin.im/post/7104547498491904036