Androidスレッド、Handler
緒論
昨年のオペレーティングシステムの授業でプロセスとスレッドを学びました.非常に理論化と抽象化されていて、JavaScriptで符号化する場合、スレッドについてのことはあまりないので(明らかですが、よくわかりませんが)、スキップしましたが、Android OSでは、このスレッドの処理も実際には重要なので、少し時間をかけて調べてみたいと思います.
プロセスとスレッドを簡単に理解する必要があります.プロセスは、プログラムを起動するときに実行をプロセスと呼び、複数のタスクを同時に実行するためにスレッドを実行します.
通常、プロセス内のスレッドは線のように実行されます.多くの人がそう形容している.それ以外にも,マルチプロセッシングとマルチスレッド共有リソースによる差異や処理方式などのコンピュータ工学的な差異は,深く検討すれば非常に深刻であるが,1つのプログラムが実行されると1つのプロセスが生成され,その中で複数のスレッドが生成され,同時に複数のタスクが処理されることを知ればよい.
Androidスレッド
アンドロイドosではスレッドが2種類に分かれています.1つはメインスレッド(UIスレッド)とワークスレッド(Workerスレッド)です.メインスレッドは、その名の通りメインタスクを行うスレッドであり、UIタスクを実行できるスレッドである.次に、残りのすべての他のスレッドをワークスレッドと呼びます.
なぜスレッドを2つに分けるのですか?次のコードを見てください.
val firstButton = findViewById<Button>(R.id.first_button)
val text = findViewById<TextView>(R.id.text)
var i = 0
firstButton.setOnClickListener{
for(i in 1..100000000L){
text.text = "${i}번째 text"
}
}
レイアウトにボタンを入力し、ボタンを押すとiが1つ増え、その値をボタンに入れてみます.しかし、このようにエンコードされたアンドロイドシミュレータを設定してボタンを押すと、アプリケーションはすぐに消えてしまいます.理由は何ですか.プライマリ・スレッドは1本の線のように長いため、1つまたは2つの順序で要求を処理し、そこでfor文を計算し、何の操作もできません.
しかし、アンドロイドシステムを開発する際には、これらの作業を行う必要があることが発生します.以上のコード程度ではないが,UIタスクを同時に実行する必要があることが起こる.そのため、Androidはワークスレッドというものを生成し、単独で演算する必要があります.
すなわち、プライマリ・スレッドではなく、時間がかかる重複タスクによっては、作業スレッドを個別に生成する必要があります.
class MainActivity : AppCompatActivity() {
private lateinit var myText: TextView
private lateinit var startButton: Button
private lateinit var myThread: MyThread
private val TAG: String = "로그"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
Log.d(TAG, "MainActivity - onCreate: ");
startButton = findViewById(R.id.start_button)
myText = findViewById(R.id.my_text)
myThread = MyThread()
startButton.setOnClickListener{
Log.d(TAG, "MainActivity - onCreate: 스타트 버튼 클릭");
myThread.start()
myText.text="world hello"
}
}
inner class MyThread: Thread(){
override fun run() {
for(i in 1..100000000L){
Log.d(TAG, "MyThread - run: i : $i ");
SystemClock.sleep(1000)
}
}
}
}
このようにしてワークスレッドを作成してfor文を切り替え、textを指定することで、プライマリスレッドは干渉を受けずにtext値を変更できます.ただし、myText.text="world hello"
のmyThread
メソッドにrun
部分を入れると、アプリケーションはすぐに離れます.UI演算はメインスレッドのみで行うことが約束されているからである.UIに関する操作は、メインスレッド(UIスレッド)でのみ行えます.この概念を熟知しなければならない.
では、UI関連のタスクはメインスレッド上でしか実行できないのはなぜでしょうか.ボタンが1つある場合、ボタン内の
text
の値はメインスレッドで指定してもよいし、他の操作スレッドで指定してもよい.まず、UIスレッドでは、あるボタンのテキスト値をボタン1と呼ぶ.このような競合が発生すると、アプリケーションに問題が発生するのは当然です.そのため、AndroidではUI関連のタスクはメインスレッドでのみ実行できます.(これにより、ユーザは、1つのスレッド内でUIを順番に処理することができる.)
それ以外にjavascriptは単一スレッドに基づいており、
setTimeout
のような演算が発生すると、自動的にこのタスクをバックグラウンドに配置し、イベントループによって処理されますが、Android、kotlin、javaでは、開発者が自らスレッドを作成し、処理する必要があります.これらの仕事がどのように行われているかを理解してみましょう.マニピュレータ
まず、これまで学んだことの一部を明確にする必要があります.一つはスレッドであり,これはコンピュータエンジニアリング,開発分野の共通内容であるが,UIスレッドとワークスレッドの区分,および現在学習しているHandlerはAndroid独自の概念である.Handlerは、ユーザが作業スレッドでUIを使用するのを助けることができる.
class MainActivity : AppCompatActivity() {
private lateinit var myText: TextView
private lateinit var startButton: Button
private lateinit var stopButton: Button
private lateinit var myThread: MyThread
private lateinit var myHandler: MyHandler
private var isRunning: Boolean = false
private val TAG: String = "로그"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
Log.d(TAG, "MainActivity - onCreate: ");
startButton = findViewById(R.id.start_button)
stopButton = findViewById(R.id.stop_button)
myText = findViewById(R.id.my_text)
isRunning = true
myThread = MyThread()
myHandler = MyHandler()
startButton.setOnClickListener{
Log.d(TAG, "MainActivity - onCreate: 스타트 버튼 클릭");
myThread.start()
isRunning = true
}
stopButton.setOnClickListener {
isRunning = false
}
}
inner class MyThread: Thread(){
override fun run() {
while(isRunning){
SystemClock.sleep(1000)
myHandler.sendEmptyMessage(0)
}
}
}
inner class MyHandler: Handler(){
override fun handleMessage(msg: Message) {
super.handleMessage(msg)
Log.d(TAG, "MyHandler - handleMessage: msg : $msg ");
var now = System.currentTimeMillis()
myText.text = "now : $now"
}
}
}
コードを少しずつ外す private var isRunning: Boolean = false
startButton.setOnClickListener{
Log.d(TAG, "MainActivity - onCreate: 스타트 버튼 클릭");
myThread.start()
isRunning = true
}
stopButton.setOnClickListener {
isRunning = false
}
スレッドをisRunning
に変換するかどうかは、上記のコードによって決定される.その後、startButton
およびstopButton
のクリックリスナーに登録して変更できます.startButton
をクリックしてスレッドを実行し、stopButton
をクリックしてスレッドの実行を停止します.inner class MyThread: Thread(){
override fun run() {
while(isRunning){
SystemClock.sleep(1000)
myHandler.sendEmptyMessage(0)
}
}
}
上のコードはisRunning
であり、true
であれば、startButton
をクリックして現在の時間を計算し、1秒待ってからmyHandler
にメッセージを送信します.現在、このsendEmptyMessage
はスレッド内でのみHandlerを起動する役割を果たしている. inner class MyHandler: Handler(){
override fun handleMessage(msg: Message) {
super.handleMessage(msg)
Log.d(TAG, "MyHandler - handleMessage: msg : $msg ");
var now = System.currentTimeMillis()
myText.text = "now : $now"
}
}
そして皆が望むHandlerHandlerはスレッドからメッセージを受信し、UIを使用します.コンストラクションが完了したら、シミュレータでボタンを押すと、text
1秒ごとに変更が表示されます.すなわち、ワークスレッドではHandlerによりUI操作が行われる.これに基づいて,プロセッサを計算値ではなくUIのみを使用する操作に分割することを提案する.
inner class MyThread: Thread(){
override fun run() {
while(isRunning){
var now = System.currentTimeMillis()
Log.d(TAG, "MyThread - run: now : $now ");
SystemClock.sleep(1000)
var msg = Message()
msg.what = 0
msg.obj = now
myHandler.sendMessage(msg)
}
}
}
inner class MyHandler: Handler(){
override fun handleMessage(msg: Message) {
super.handleMessage(msg)
myText.text = "now : ${msg.obj}"
}
}
前述したように、スレッドとHandlerコードを変更すればよい.now
オブジェクトを使用してMessage
変数を生成し、msg
および.what
を定義します..obj
Handlerに送信したいデータ、すなわち計算されたobj
が送信され、now
は通常、what
構文when
がどのように処理されるかを区別するために使用される.ただし、
obj
をもう一度押すと、スレッドのライフサイクルに関係するアプリケーションのハングアップが決定されます.次に議論する情報キューとルパーの概念も写真の中で、まず、テーマは
ねじの作成→ねじの実行→ねじの終了(消去)
手順に従って、スタートボタンを押した瞬間
startButton
オブジェクトmyThread
が作成されたため、手順をスキップした.したがって、再度ボタンを押すと、start
メソッドを実行する矛盾が生じる.だから startButton.setOnClickListener{
myThread = MyThread()
Log.d(TAG, "MainActivity - onCreate: 스타트 버튼 클릭");
myThread.start()
}
必要に応じてリスナーでスレッドの生成を続行すると、アプリケーションを閉じずに複数のスレッドが生成されます.n/a.結論
Androidでは、重要なメインスレッド、ワークスレッド、Handler、Loperのコンセプトを熟知するために、一生懸命Googleプログラミングをしていましたが、理解しにくい点が多かったのでYouTubeでよく説明している動画を見て、Handlerのベースから学びました.オペレーティングシステムの授業を受ける時、多くの理論が学べない地方があって、このような実務的な地方が適用することを発見して、専門知識を学ぶ時間に対しても少しの意義を見つけることができます.しかし、Handlerが発表されるたびに、すでに
start
になっている言葉が出てきます.やはりAndroid分野も非常に速い分野です.Reference
この問題について(Androidスレッド、Handler), 我々は、より多くの情報をここで見つけました https://velog.io/@peppermint100/안드로이드-스레드-핸들러-루퍼テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol