Android Studio

Volley Error 해결 - RequestQueue 오류, Context오류

리콜 2022. 11. 20. 02:50

저번에 만든 Volley를 사용하여 만든 api요청에서 처음에는 동작하지만 다시 앱을 실행시키거나 하면 앱이 강제 종료 되거나 액티비티를 실행 못하는 오류가 있었다. Debug 내용을 보면 

E/AndroidRuntime: FATAL EXCEPTION: Thread-3
    Process: com.akj.sns_project, PID: 12852
    java.lang.NullPointerException: Attempt to invoke virtual method 'com.android.volley.Request com.android.volley.RequestQueue.add(com.android.volley.Request)' on a null object reference
        at com.akj.sns_project.Fragment01.makeRequest(Fragment01.java:313)
        at com.akj.sns_project.Fragment01$1.run(Fragment01.java:88)
        at java.lang.Thread.run(Thread.java:1012)

라고 나온다 여러번 오류를 해결하려 찾으러 다녔지만 열심히 찾은 결과 대충 context오류 즉 프로그램 사이클 적으로 잘못 되었다는 것을 알았다. 이를 관리하기 위해서는 RequestQueue를 관리해주는 클래스를 하나 만드는 것이었다. 외국 사람들은 AppController라는 클래스를 만들어 RequestQueue를 관리하는데  하지만 사람들이 올려 놓은 AppController는 자신들의 코드에 맞게 맞춰둔거라 옮겨 쓰기에 맞지않았다. 그래서 찾다가 발견한것이 

안드로이드 문서에서 RequestQueue 부분에서 RequestQueue를 싱글톤으로 사용하는 것을 권장하고 있었고 예시 코드가 사람들이 올려뒀던 AppController랑 비슷해서 다음과 같이 수정하였다.

public class AppController extends Application {
    private static AppController instance;
    private RequestQueue requestQueue;
    private static Context ctx;

    private AppController(Context context) {
        ctx = context;
        requestQueue = getRequestQueue();

    }

    public static synchronized AppController getInstance(Context context) {
        if (instance == null) {
            instance = new AppController(context);
        }
        return instance;
    }

    public RequestQueue getRequestQueue() {
        if (requestQueue == null) {
            // getApplicationContext() is key, it keeps you from leaking the
            // Activity or BroadcastReceiver if someone passes one in.
            requestQueue = Volley.newRequestQueue(ctx.getApplicationContext());
        }
        return requestQueue;
    }

    public <T> void addToRequestQueue(Request<T> req) {
        getRequestQueue().add(req);
    }



}

이미지를 불러오는것은 일단 제거 해두고 싱글톤클래스 명을 Controller로 변경하여 사용하였다. 

그 뒤 저번에 작성하였던 RequestQueue.Add를 수정하였다.

public void makeRequest(String url)
    {
        StringRequest request = new StringRequest(Request.Method.GET, url, new Response.Listener<String>() {
            @Override
            public void onResponse(String response) {
                Log.v("output popular", response); //요청 출력해보기
                Gson gson = new Gson();  //gson라이브러리 선언

                MovieList movieList = gson.fromJson(response, MovieList.class); //gson으로 Json파일 object로 변환
                Movie movie = movieList.results.get(0);
                Log.v("movie name", movie.poster_path.toString());
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                Log.e("error ", error.getMessage());
            }
        }
        ){
            protected  Map<String, String> getParams() throws AuthFailureError{
                Map<String, String> params = new HashMap<String, String>();

                return params;
            }
        };
        request.setShouldCache(false);
        Log.v("SendRequest","요청 보냄");

        //requestQueue.add(request);

        AppController.getInstance(getActivity()).addToRequestQueue(request);  //gson리퀘스트 큐에 넣기


    }

마지막 라인의 주석으로 바뀐부분이 기존에 사용하던 방식, AppController클래스의 싱글톤을 불러와 add해주었다.

이 후 잘 작동하였다. 

만약 이렇게 해도 동작하지 않는다면 manifest파일에 클래스를 넣어줘야한다는데 내경우에는 없어도 잘동작하였다.

 

결론 :  RequestQueue는 싱글톤으로 하나의 객체만 만들어 관리하자!

반응형