原理はこれであることが判明しました!2021 ByteDance + JD + Meituanインタビューサマリー!仕事を探しているAndroid開発者に手紙を書く

Jinjiuyin 10以降、すべての主要なオンラインプラットフォームは、オファーを受けた人や面接に失敗した人など、さまざまな経験を共有します。ほとんどの人は大手企業からお気に入りのオファーを受け取っていると思いますが、それらに参加できなかった人もいます。 ?憧れの大工場に悩まされているのですが、どうすれば大工場に入ることができますか?大工場に入る準備はどうしたらいいですか?

現時点で、Byteのディレクターは、インタビューのByteDanceに関して、上司がいくつかのインタビューのポイントを要約したと言います。それは他のインタビューにも大いに役立つと思います。今日、私はそれを整理し、もっとお役に立てば幸いです。たくさんの友達。

1.MVVMアーキテクチャパターンの概要

これは、MVVMアーキテクチャモデル+ Kotlinコルーチン+ JetPack(ViewModel + LiveData)+ Retrofitアーキテクチャを使用してWanAndroidログインインターフェイスの小さなデモを実装することであり、WanAndroidクライアントはフォローアップで徐々に改善されます

1、ViewModel

ビューデータの所有権をインターフェイスコントローラーのアクティビティ/フラグメントロジックから分離するために、アーキテクチャコンポーネントは、インターフェイスのデータの準備を担当するインターフェイスコントローラーのViewModel補助プログラムクラスを提供します。ViewModelオブジェクトは構成の変更中に自動的に保持されるため、それらが格納するデータは、次のアクティビティまたはフラグメントインスタンスですぐに使用できます。

2、LiveData

LiveDataは、ライフサイクルを認識できる監視可能なデータストレージクラスです。つまり、アクティビティ、フラグメント、サービスなどの他のアプリケーションコンポーネントのライフサイクルに従い、LiveDataがアクティブなライフサイクル状態のアプリケーションコンポーネントオブザーバーのみを更新するようにします。LiveDataオブジェクトは通常ViewModelオブジェクトに保存され、getterメソッドを介してアクセスできます。

3.Kotlinコルーチン

コルーチンはスレッドにアタッチされており、非同期コードの順次書き込みと自動スレッド切り替えを実現できます。また、ViewModelScopeは、アプリケーションの各ViewModelのViewModelScopeを定義します。ViewModelがクリアされている場合、この範囲で開始されたコルーチンは自動的にキャンセルされます。

4、後付け

Kotlinスレッドをサポートするために、サービスインターフェイスのネットワークリクエスト関数をサスペンドインターフェイス関数として宣言し、サスペンド関数の結果をLiveDataオブジェクトとして送信します。

2、ViewModel

//获取ViewModel
viewModel = ViewModelProvider(this).get(MainViewModel::class.java)` 

ViewModelオブジェクトが存在する時間範囲は、ViewModelが取得されたときにViewModelProviderに渡されるライフサイクルです。ViewModelは、その存在時間範囲を制限するライフサイクルが完全になくなるまでメモリに残ります。アクティビティの場合はアクティビティが完了したとき、フラグメントの場合はフラグメントが分離されたときです。

3、LiveData

//对User数据进行观察
viewModel.user.observe(this, Observer {
    //展示登录结果
    if (it.errorCode == 0) {
        Toast.makeText(this, it.data?.nickname, Toast.LENGTH_SHORT).show()
    } else {
        Toast.makeText(this, it.errorMsg, Toast.LENGTH_SHORT).show()
    }
})

LiveDataを使用すると、次の利点があります。インターフェイスがデータ状態に準拠していることを確認する

LiveData 遵循观察者模式。当生命周期状态发生变化时,LiveData 会通知 Observer 对象。您可以整合代码以在这些 Observer 对象中更新界面。观察者可以在每次发生更改时更新界面,而不是在每次应用数据发生更改时更新界面。

メモリリークはありません

观察者会绑定到 Lifecycle 对象,并在其关联的生命周期遭到销毁后进行自我清理。

アクティビティが停止してもクラッシュは発生しません

如果观察者的生命周期处于非活跃状态(如返回栈中的 Activity),则它不会接收任何 LiveData 事件。
不再需要手动处理生命周期
界面组件只是观察相关数据,不会停止或恢复观察。LiveData 将自动管理所有这些操作,因为它在观察时可以感知相关的生命周期状态变化。

データは常に最新です

如果生命周期变为非活跃状态,它会在再次变为活跃状态时接收最新的数据。例如,曾经在后台的 Activity 会在返回前台后立即接收最新的数据。

適切な構成変更

如果由于配置更改(如设备旋转)而重新创建了 Activity 或 Fragment,它会立即接收最新的可用数据。

リソースを共有する

可以使用单一实例模式扩展 LiveData 对象以封装系统服务,以便在应用中共享它们。

4.Kotlinコルーチン

4.1、非同期の本質

非同期とは何ですか?

异步就是同时进行一个以上彼此目的不同的任务。

しかし、前面と背面の依存関係があるタスクの場合、非同期を処理する方法は?

利用异步中的回调机制处理。

なぜ非同期コールバックメカニズムが必要なのですか?

因为不同的任务之间存在前后的依赖关系。

非同期コールバックメカニズムの欠点は何ですか?

代码结构过分耦合,遇到多重函数回调的嵌套耦合,也就是回调地狱,代码会难以维护。

地獄をコールバックするための解決策は何ですか?

链式调用结构。
常见方式就是使用RxJava,它是反应函数式编程在Java中的实现。
但是RxJava中流的创建、转化与消费都需要使用到各种类和丰富的操作符,加大了RxJava的学习成本。
减少在无封装情况下使用RxJava,因为你无法保证团队里面的每一个成员都能看懂它,并且在修改时都能做出正确选择。

シリアル実行では、コードは実際には順次実行されますが、実際には異なるスレッドで順次実行されます。では、なぜシリアル実行でコードの実行順序は同じであるのに、コールバックが引き続き使用されるのでしょうか。

因为串行的执行中,执行是阻塞式的,主线程的阻塞会导致很严重的问题,所以所有的耗时操作不能在主线程中执行,所以就需要多线程并行来执行。

並列実行では、非同期コールバックは実際にはコードのマルチスレッド順次実行です。コードを順番に記述するだけでなく、スレッドの切り替え作業を自動的に完了するために、コードを異なるスレッドで実行できるようにすることはできますか?

那就是Kotlin协程。
Kotlin 的协程是一种无栈协程的实现,它的控制流转依靠对协程体本身编译生成的状态机的状态流转来实现,变量保存也是通过闭包语法来实现的。

結論として:

异步回调就是代码的多线程顺序执行,而Kotlin协程可以实现顺序编写异步代码,自动进行线程切换。

では、コルーチンによる自動スレッド切り替えの原理は何ですか?

Yield:让出CPU,放弃调度控制权,回到上一次Resume的地方
Resume:获取调度控制权,继续执行程序,到上一次Yield的地方

例:

1. GlobalScope.launch发起了一个协程,并在IO线程上执行,
2\. 在协程里,去调用接口获取结果。
3. 拿到结果,使用withContext(Dispatchers.Main)切换到主线程并更新界面

4.2、コルーチンのタイプ

是协程范围,指的是协程内的代码运行的时间周期范围,如果超出了指定的协程范围,协程会被取消执行。

GlobalScope

指的是与应用进程相同的协程范围,也就是在进程没有结束之前协程内的代码都可以运行。

JetPackで提供されるライフサイクル対応コルーチンの範囲:

ViewModelScope,为应用中的每个 ViewModel 定义了 ViewModelScope。如果 ViewModel 已清除,则在此范围内启动的协程都会自动取消。

LifecycleScope,为每个 Lifecycle 对象定义了 LifecycleScope。在此范围内启动的协程会在 Lifecycle 被销毁时取消。

使用 LiveData 时,可能需要异步计算值。可以使用 liveData 构建器函数调用 suspend 函数,并将结果作为 LiveData 对象传送。

関連リンク:https://developer.android.google.cn/topic/libraries/architecture/coroutines

4.3、コルーチンの開始

起動方法:

/**
 * 重要知识:ViewModel+协程
 */
fun ViewModel.launch(
    block: suspend CoroutineScope.() -> Unit,
    onError: (e: Throwable) -> Unit = {},
    onComplete: () -> Unit = {}
) {
    viewModelScope.launch(CoroutineExceptionHandler { _, e -> onError(e) }) {
        try {
            block.invoke(this)
        } finally {
            onComplete()
        }
    }
}

ソースコード:

public fun CoroutineScope.launch(
    context: CoroutineContext = EmptyCoroutineContext,
    start: CoroutineStart = CoroutineStart.DEFAULT,
    block: suspend CoroutineScope.() -> Unit
): Job {
    val newContext = newCoroutineContext(context)
    val coroutine = if (start.isLazy)
        LazyStandaloneCoroutine(newContext, block) else
        StandaloneCoroutine(newContext, active = true)
    coroutine.start(start, coroutine, block)
    return coroutine
}

4.3.1、起動方法の説明

環境

协程上下文,可以指定协程运行的线程。默认与指定的CoroutineScope中的coroutineContext保持一致,比如GlobalScope默认运行在一个后台工作线程内。也可以通过显示指定参数来更改协程运行的线程,Dispatchers提供了几个值可以指定:Dispatchers.Default、Dispatchers.Main、Dispatchers.IO、Dispatchers.Unconfined。

開始

协程的启动模式。默认的CoroutineStart.DEFAULT是指协程立即执行,除此之外还有CoroutineStart.LAZY、CoroutineStart.ATOMIC、CoroutineStart.UNDISPATCHED。

ブロック

协程主体。也就是要在协程内部运行的代码,可以通过lamda表达式的方式方便的编写协程内运行的代码。

CoroutineExceptionHandler

指定CoroutineExceptionHandler来处理协程内部的异常。

ジョブ

返回值,对当前创建的协程的引用。可以通过Job的start、cancel、join等方法来控制协程的启动和取消。

4.4、サスペンド機能

suspendキーワードは、この関数が時間のかかる操作であり、コルーチンで実行する必要があることを示すためにのみ機能しますが、withContextメソッドはスレッドの切り替えを実行します。

コルーチンのコードは自動的に他のスレッドに切り替わり、次に自動的にメインスレッドに戻ります。シーケンシャル書き込みは論理的な直観性を保証し、コルーチンの自動スレッド切り替えはコードの非ブロッキング性を保証します。サスペンド関数は、コルーチンまたは他のサスペンド関数で呼び出す必要があります。つまり、サスペンド関数は、コルーチンで直接または間接的に実行する必要があります。

では、なぜコルーチンのコードがメインスレッドで実行されないのですか?また、実行後に自動的にメインスレッドに戻るのはなぜですか?

コルーチンの中断は、コルーチン内のコードがコルーチンが配置されているスレッドを離れるプロセスとして理解でき、コルーチンの回復は、コルーチン内のコードがスレッドに再び入るプロセスとして理解できます。コルーチンがあります。コルーチンは、このサスペンドリカバリメカニズムを介してスレッドを切り替えることです。

4.5、async awaitMethod

asyncメソッドを使用して、suspendメソッドをラップして同時リクエストを実行します。同時結果が返された後、メインスレッドに切り替えてから、awaitメソッドを使用して同時リクエストの結果を取得します。

5、改造

HTTPインターフェースサスペンド機能:

interface ApiService {
    @FormUrlEncoded
    @POST("user/login")
    suspend fun loginForm(@Field("username")  username: String,@Field("password")  password: String): BaseResponse<User>
}

Kotlinジェネリック:

data class BaseResponse<T>(
    val errorCode: Int=0,
    val errorMsg:String? = null,
    var data: T? = null
)

これは、MVVMアーキテクチャモデル+ Kotlinコルーチン+ JetPack(ViewModel + LiveData)+ Retrofitアーキテクチャを使用してWanAndroidログインインターフェイスの小さなデモを実装することであり、WanAndroidクライアントはフォローアップで徐々に改善されます

最後に書く

技術分野では、修了後に一度だけできるコースはなく、「マスターがドアをリードし、練習は個人によって異なります」というコースがベストです。「果てしなく学ぶ」という言葉は、あらゆる技術分野での良い習慣であるだけでなく、プログラマーやエンジニアが時代によって排除されないようにし、より良い機会と開発を得るために必要な前提条件でもあります。

学習効率が低く、正しいガイダンスが不足していると感じた場合は、豊富なリソースと強力な学習環境を備えたテクニカルサークルに参加して、一緒に学習し、コミュニケーションをとることができます。

参加しませんか!グループには多くの第一線の技術専門家がいるだけでなく、小さな工場やアウトソーシング企業で苦労しているコードファーマーもいます。私たちは平等で高品質のAndroidコミュニケーションサークルの作成に取り組んでいます。全員を作ることは不可能かもしれません。技術は短期的には飛躍的に進歩します。長期的には、ビジョン、パターン、および長期的な開発の方向性が最も重要です。

35歳の中年の危機は、主に短期的な利益に導かれ、時期尚早に価値を絞り出すことによって引き起こされます。最初から正しい長期的なキャリアプランを確立できれば。35歳を過ぎると、あなたは周りの人よりも価値が高くなります。

%E4%BC%9A%E8%BF%99%E4%BA%9B%EF%BC%9F%E5%A6%82%E4%BD%95%E9%9D%A2%E8%AF%95%E6 %8B%BF%E9%AB%98%E8%96%AA%EF%BC%81.md)!**

参加しませんか!グループには多くの第一線の技術専門家がいるだけでなく、小さな工場やアウトソーシング企業で苦労しているコードファーマーもいます。私たちは平等で高品質のAndroidコミュニケーションサークルの作成に取り組んでいます。全員を作ることは不可能かもしれません。技術は短期的には飛躍的に進歩します。長期的には、ビジョン、パターン、および長期的な開発の方向性が最も重要です。

35歳の中年の危機は、主に短期的な利益に導かれ、時期尚早に価値を絞り出すことによって引き起こされます。最初から正しい長期的なキャリアプランを確立できれば。35歳を過ぎると、あなたは周りの人よりも価値が高くなります。

おすすめ

転載: blog.csdn.net/a120464/article/details/113930855