본문 바로가기

Android/최적화

[안드로이드/Java] AsyncTask 화면 넘김시 중단하는 법, http 요청 중단하는 법

728x90
반응형

 

 

http요청을 AsyncTask를 이용해 구현했는데요,

프래그먼트가 넘어갈때 요청을 중단하고 싶어서 cancle(true)를 사용했습니다.

AsyncTask의 변수를 멤버변수로 두고, onStop()에서 cancle을 하여 진행중인 AsyncTask를 종료하려고 하였죠.

@Override
public void onStop() {
    super.onStop();
    if(networkTask!=null)
       networkTask.cancel(true);
}

그런데 한번에 해결될 일은 없죠 ㅎㅎㅎ

이것만으로는 중단이 안되더군요.

이유는 canel을 하면 onPostExecute로 넘어가지 않는것 뿐이고, doInBackGround는 전부 동작한다는 것.

또한 http요청은 계속 진행중이라는 것.

두가지 문제를 해결해야 했습니다.

doInBackGround를 중단하기 위해서는 while문을써 isCancelled()가true가 되는지 계속 확인해주어야 하기 때문입니다.

 @Override
protected String doInBackground(Void... params) {

     while(/*condition..*/)) {
          /* .. 
          your code
          .. */
         if (isCancelled()) {
                break; 
          }
     }          
     return result;
}

이렇게요. 단순히 doInBackground를 중단시키고 싶으면 위의 두 코드만으로 해결이 됩니다 ^^

하지만 저는 진행중인 htttp요청도 중단시켜야 했는데요.

http요청은 Future를 써 중단하였습니다.

private Future<String> future;
private final ExecutorService executor = Executors.newCachedThreadPool(Executors.defaultThreadFactory());

String형은 http요청 result값입니다. 위처럼 선언해주고,

http 요청 코드를 future로 감싸줍니다.

future = executor.submit(new Callable<String>() {
    @Override
    public String call() throws IOException {
        String result = null;
        RequestHttpURLConnection requestHttpURLConnection = new RequestHttpURLConnection();
        try {
             //here http request code
             result = requestHttpURLConnection.request(url, null); 
        } finally {
             //here http disconnect code
             requestHttpURLConnection.urlConn.disconnect(); //disconnect
        }
        return result;
     }
 });

 AsyncTask 생성자에 넣어주었습니다.

그다음은 doInBackground안에 future.get()을 while문안에 넣어야하는데요.

isCancelled()를 계속 보기 위함이고, result값이 나오면 doInBackground를 끝내기 위함입니다.

그래서 while문안에 있어도 http요청은 한번만 할 수 있도록 해주었습니다. 밑은 저의 http요청 AsyncTask입니다.

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

        private String url;
        private Future<String> future;
        private final ExecutorService executor = Executors.newCachedThreadPool(Executors.defaultThreadFactory());

        NetworkTask(String url) {
            this.url = url;
            future = executor.submit(new Callable<String>() {
                @Override
                public String call() throws IOException {
                    String result = null;
                    RequestHttpURLConnection requestHttpURLConnection = new RequestHttpURLConnection();
                    try {
                        result = requestHttpURLConnection.request(url, null); // 해당 URL로 부터 결과물을 얻어온다.
                    } finally {
                        requestHttpURLConnection.urlConn.disconnect();
                        //disconnect
                    }
                    return result;
                }
            });

        }

        @Override
        protected void onPreExecute(){
          ..
        }

        @Override
        protected String doInBackground(Void... params) {

            String result = "wait_result";
            boolean isHttpRunning = false;
            while(result.equals("wait_result")) {
                if(!isHttpRunning) {
                    try {
                        isHttpRunning = true;
                        result = future.get();
                    } catch (ExecutionException | InterruptedException e ) {
                        e.printStackTrace();
                    }
                }

                if (isCancelled()) {
                    future.cancel(true);
                    break;
                }
            }

            return result;
        }

        @Override
        protected void onPostExecute(String json) {
            super.onPostExecute(json);
            ...
        }
    }

 

http요청부분은 사용자에 맞게 수정하여야 할 것입니다. 

이렇게 저는 http요청 도중 화면이 넘어갈때 asyncTask도 빠져나오고, http요청도 중단하는걸 성공했습니다!

728x90
반응형