안드로이드 AsyncTask 에 관한 질문입니다.


AsyncTask 에 대한 문서를 읽은적이 있어서 아래와 같이 간단하게 프로그램을 짜봤습니다. 그런데 제대로 작동이 안되네요... 어떻게 수정하면 될까요?

package com.test;

import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.provider.Settings.System;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.view.View.OnClickListener;

public class AsyncTaskActivity extends Activity {
    Button btn;
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        btn = (Button) findViewById(R.id.button1);
        btn.setOnClickListener((OnClickListener) this);
    }

    public void onClick(View view){
        new LongOperation().execute("");
    }

    private class LongOperation extends AsyncTask<String, Void, String> {
        @Override
        protected String doInBackground(String... params) {
            for(int i=0;i<5;i++) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            TextView txt = (TextView) findViewById(R.id.output);
            txt.setText("Executed");
            return null;
        }

        @Override
        protected void onPostExecute(String result) {
        }

        @Override
        protected void onPreExecute() {
        }

        @Override
        protected void onProgressUpdate(Void... values) {
        }
    }
}

백그라운드 프로세스에서 5초후에 라벨의 내용을 변경하고 싶어요.

아래 제가 작성한 main.xml파일입니다.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="fill_parent"
              android:layout_height="fill_parent"
              android:orientation="vertical" >
    <ProgressBar
        android:id="@+id/progressBar"
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:indeterminate="false"
        android:max="10"
        android:padding="10dip">
    </ProgressBar>
    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Start Progress" >
    </Button>
    <TextView android:id="@+id/output"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Replace"/>
</LinearLayout>
  • 2016년 06월 14일에 작성됨

조회수 182


1 답변


좋아요
0
싫어요
채택취소하기

지금 별도의 스레드를 통해서 GUI에 접근하고 싶은 것 같은데요. 메인 메소드에서의 그러한 접근 시도는 좋지 않아요.

AsyncTask는 GUI에 대한 접근 권한이 없는 다른 스레드내에서 작동하며 모든 작업을 doInBackground()메소드에서 처리합니다.

preExecute(), postExecute()메소드는 새로운 스레드에서의 큰 작업 전후에 GUI에 접근할 수 있도록 권한을 부여합니다. 또한 긴 시간을 필요로하는 작업을 끝낸 후에는 postExecute() 메소드로 작업의 결과를 보내 작업의 결과를 확인할 수 있습니다.

아래 코드가 TextView를 최신화하는 부분일 것으로 예상됩니다.

TextView txt = (TextView) findViewById(R.id.output);
txt.setText("Executed");

이 코드를 postExecute()메소드에 삽입하세요. 그러면 doInBackground 메소드가 실행된 후에 TextView가 정상적으로 최신화되는 것을 확인할 수 있을겁니다.

수정: 작성하신 코드에는 onClick listener에서 어떤 View가 선택됐는지 확인하는 과정이 없습니다. 이런 문제를 해결하기위해 switch문을 활용하는 간단한 방법을 알려드리겠습니다. 혼란을 주고 있는 부분을 해결해 줄 수정된 class를 아래와 같이 만들어봤습니다. 확인해보세요.

import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.provider.Settings.System;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.view.View.OnClickListener;

public class AsyncTaskActivity extends Activity implements OnClickListener {

    Button btn;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        btn = (Button) findViewById(R.id.button1);
        // because we implement OnClickListener we only have to pass "this"
        // (much easier)
        btn.setOnClickListener(this);
    }

    public void onClick(View view) {
        // detect the view that was "clicked"
        switch (view.getId()) {
        case R.id.button1:
            new LongOperation().execute("");
            break;
        }
    }

    private class LongOperation extends AsyncTask<String, Void, String> {

        @Override
        protected String doInBackground(String... params) {
            for (int i = 0; i < 5; i++) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    Thread.interrupted();
                }
            }
            return "Executed";
        }

        @Override
        protected void onPostExecute(String result) {
            TextView txt = (TextView) findViewById(R.id.output);
            txt.setText("Executed"); // txt.setText(result);
            // might want to change "executed" for the returned string passed
            // into onPostExecute() but that is upto you
        }

        @Override
        protected void onPreExecute() {}

        @Override
        protected void onProgressUpdate(Void... values) {}
    }
}
  • 2016년 06월 15일에 작성됨

로그인이 필요한 기능입니다.

Hashcode는 개발자들을 위한 무료 QnA사이트 입니다. 작성한 답변에 다른 개발자들이 댓글을 작성하거나 좋아요/싫어요를 할 수 있기 때문에 계정을 필요로 합니다.
► 로그인
► 계정만들기
Close