마스터Q&A 안드로이드는 안드로이드 개발자들의 질문과 답변을 위한 지식 커뮤니티 사이트입니다. 안드로이드펍에서 운영하고 있습니다. [사용법, 운영진]

AsyncTask로 Json을 받아서 RecyclerView에 출력하려 합니다.

0 추천
MainActivity안에 AsyncTask를 상속받는 클래스를 만들어서 Json을 불러오고,

데이터를 다 불러오면 RecyclerView에 출력하려고합니다.

 

AsyncTask에 관해서 찾아보니,

doInBackground 작업이 끝나면 onPostExecute가 실행된다고 하길래,

onPostExecute에서 RecyclerView의 데이터를 집어 넣는다고 생각하고,

 

로그 찍어서 테스트해보니,

[doInBackground - onPostExecute - doInBackground.onResponse]

순서로 로그가 찍히더라구요.....ㅠ

 

 

1. AsyncTask의 작업이 끝났는지 여부를 어떻게 알 수 있을까요??

2. AsyncTask를 상속받느라 내부클래스로 만들었는데, 여기서 mainActivity의 메소드를 쓰려면 어찌해야할까요?

무식하게 new로 만들어서 해보니 에러가 뜨더라구요 ㅠㅠ
떡빵s (1,370 포인트) 님이 2018년 11월 27일 질문

2개의 답변

+1 추천
 
채택된 답변

AsyncTask 에서 doInBackground 가 두번 호출된것이 좀 이상한데 Asynctask는 프로그램쓰레드가 홀딩 되는것을 방지하기 위해 네트워크 이슈와 같은 대기 이슈로 인해 사용됩니다. 

혹시 asynctask 를 여러번 호출한건 아닌지 의심됩니다. 

일반적으로는 asynctask 에서는 doInBackground 의 작업이 끝나야 onPostExecute  가호출됩니다. ㅏ

[doInBackground - onPostExecute - doInBackground.onResponse] 이렇게 나오는것 뭔가 싱크가 맞지 않습니다. asynctask를 여러번 호출하는것은 아닌지 확인 해보세요. 

산적 (1,360 포인트) 님이 2018년 11월 28일 답변
떡빵s님이 2018년 11월 28일 채택됨
private void StartAsync() {
        AsyncRetrofit asyncRetrofit = new AsyncRetrofit();
        asyncRetrofit.execute();

    }


class AsyncRetrofit extends AsyncTask<String, String, String> {

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            progressON();
        }

        @Override
        protected String doInBackground(String... strings) {

            retrofit = new Retrofit.Builder().baseUrl(ApiService.API_URL).build();
            apiService = retrofit.create(ApiService.class);


            Log.d("@@@","doInBackground Start======="+ result);



            Call<ResponseBody> comment = apiService.getComment();
            comment.enqueue(new Callback<ResponseBody>() {
                @Override
                public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
                    try {
                        result = response.body().string();
                        Log.d("@@@", "doInBackground.onResponse====="+ result);
                        tvResult.setText(result);

                        ArrayList<PhotoItem> listItem = new ArrayList<>();
                        Gson gson = new Gson();
                        PhotoItem[] pgs = gson.fromJson(result, PhotoItem[].class);

                        for(PhotoItem pg : pgs) {
                            listItem.add(new PhotoItem(pg.albumId, pg.id, pg.title, pg.url, pg.thumbnailUrl));
                        }

                        PhotoAdapter adapter = new PhotoAdapter(MainActivity.this, listItem);
                        rv_list.setLayoutManager(new LinearLayoutManager(MainActivity.this, LinearLayoutManager.VERTICAL, false));
                        rv_list.setAdapter(adapter);
                        progressOFF();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }

                @Override
                public void onFailure(Call<ResponseBody> call, Throwable t) {
                    Log.d("@@@","Fail======="+t);
                }
            });
            Log.d("@@@","doInBackground END======="+ result);
            return result;
        }

        @Override
        protected void onProgressUpdate(String... values) {
            super.onProgressUpdate(values);
            Log.d("@@@","onProgressUpdate ######### "+values[0]);

        }

        @Override
        protected void onPostExecute(String s) {
            super.onPostExecute(s);
            Log.d("@@@","onPostExecute======="+s);
            tvResult.setText(s);
        }
    }




코드 일부긴 하지만, 이런식으로 구현했는데,
로그값 보면,

doInBackground Start=======
doInBackground END=======
onPostExecute=======
 doInBackground.onResponse=====[ ~~~ ... JSON DATA ... ~~~ ]

이런식으로 나옵니다...
제가 실수한 부분이 있을까요????
위코드로 보면 올려주신 로그되로 표시되는것이 맞습니다. 레트로핏을 사용하는데 왜 AsyncTask 안에서 사용하는지 궁금하네요 레트로핏 자체가 asynctask 같은일을 하라고 쓰는건데 .. asynctask를 사용하지 않고 작성해도 되는것 같은데요.   레트포핏은 리턴을 받으면 호출되는 response가 등록되는 코드가 전달되고 doinbackground 는 끝이 나는게 정상입니다. 그리니  response 나중에 호출되는것이지요.
아....레트로핏쓰면....  async안해줘도...되나요...????;;;

예전에 httpURLconnection인가 그것만 써봐서, 쓰레드 처리해줘야하는줄 알았습니다...ㅠㅠ

호출순서도 async안에 레트로핏을 써서, 레트로핏이 늦게 끝나서 그런거였군여 ㅠ
async안에다가 async처리되는 동안에 로딩 스피너 어찌 넣을지 계속 찾아보고 있었는데,
다시 다른 방법을 찾아봐야겠습니다....ㅠㅠ

답변 감사합니다!!!
로딩스피너는 레트로핏에 onresponese 등록할때 표시되고 onresponese 콜될때 없애면 될듯한데요..
+1 추천

 onPostExecute에서 끝난 후 작업 처리하구요 

메인 클래스 메소드 쓰려면 메인 클래스 객체 주소를 가져와서 접근 해야져

0093 님이 2018년 11월 28일 답변
아, 그냥 onPostExecute에 때려넣으면 되는군요!!
계속 해당값 받아와서 쓰는 생각만했네요 ㅠ
...