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

다른 액티비티의 클래스 참조하여 객체 생성하는 방법 아시는 분 계시면 도와주시면 감사하겠습니다.ㅎㅎ

0 추천

Mainacivity.java에서 SecondActivity.java의 GetData 클래스의 객체를 생성하여 객체를 통해
메소드에 접근하고 싶습니다!  제가 짠 코드대로 하면 GetData 클래스의 doInBackground 메소드가 

호출이 아예 안 되는 것 같습니다.
혹시 어떻게 해결해야 할지 아시는 분 계신가요? 아신다면 답변 주시면 감사하겠습니다.!!
코드는 너무 길어서 중점적으로 필요한 부분만 간략하게 정리하여 붙였습니다.

//SecondActivity
package com.example.finalstudent_db;
public class SecondActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);

        class GetData extends AsyncTask<String, Void, String> {
            @Override
            protected String doInBackground(String... params) { 
                String serverURL = params[0];  
                String postParameters = "Snumber=" + params[1];
                try {
 
                    URL url = new URL(serverURL);
                    HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();

                    httpURLConnection.setReadTimeout(5000);
                    httpURLConnection.setConnectTimeout(5000);
                    httpURLConnection.setRequestMethod("POST");
                    httpURLConnection.setDoInput(true);
                    httpURLConnection.connect();

                    OutputStream outputStream = httpURLConnection.getOutputStream();
                    outputStream.write(postParameters.getBytes("euc-kr"));
                    outputStream.flush();
                    outputStream.close();

                    int responseStatusCode = httpURLConnection.getResponseCode();
                    Log.d(TAG, "response code - " + responseStatusCode);

                    InputStream inputStream; 
                    if (responseStatusCode == HttpURLConnection.HTTP_OK) {
                        inputStream = httpURLConnection.getInputStream(); 
                    } else {
                        inputStream = httpURLConnection.getErrorStream();
                    }
                    InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "euc-kr"); 
                    BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
                    
                    StringBuilder sb = new StringBuilder();
                    String line;

                    while ((line = bufferedReader.readLine()) != null) {
                        sb.append(line);
                    }

                    bufferedReader.close();
                    return sb.toString().trim();

                } catch (Exception e) {

                    Log.d(TAG, "InsertData: Error ", e);
                    errorString = e.toString();
                    return null;
                }
            }
        }
    }
}
//MainActivity
public class MainActivity extends AppCompatActivity {
    private GetData task;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button button_search = (Button) findViewById(R.id.button_main_search);
        button_search.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {

                String Keyword =  mEditTextSearchKeyword.getText().toString();
                mEditTextSearchKeyword.setText("");

                Intent intent = new Intent(MainActivity.this,SecondActivity.class);
                startActivity(intent);

                task = new GetData();
                task.execute("http://"+IP_ADDRESS+"/query.php",Keyword);

            }
        });
    }
}
갸갸 (160 포인트) 님이 2021년 5월 18일 질문
갸갸님이 2021년 5월 18일 수정

1개의 답변

+1 추천
 
채택된 답변

특별한 경우가 아니면 다른 액티비티나 프레그먼트에 있는 객체는 직접 참조하지 않습니다. 왜냐하면 안드로이드의 라이프사이클 때문에 디바이스가 회전되거나 프로세스가 앱을 죽이는 경우가 종종 생기기 때문에 이걸 위해서는 라이프사이클에 안전한 방법을 사용해서 객체를 참조해야 합니다.  Bundle, Parcelable, Serializable 등등의  타입의 객체를 Intent나 arguments를 통해 전달을 해서 사용합니다. 이렇게 하지 않으면 위에서 말씀드린 이벤트들이 발생하면 해당 객체에 더이상 접근할 수 없습니다. 이게 바로 

MainActivity activity = ...
activity.publicMethod()

같은 형태를 잘 사용하지 않는 이유입니다. 물론 사용하는 경우가 있지만, 이 때는 라이프사이클의 문제가 없다는 것이 확실할 때만 사용하셔야 합니다.

task 객체를 인터페이스를 통해서 사용하세요.

public class GetData extends AsyncTask... {
    interface Listener {
           void onSuccess();
           void onFailure();
    }

    private final Listener listener;
    public GetData(GetData.Listener listener) {
         this.listener = listener;
    }
}


public class MainActivity extends AppCompatActivitry implements GetData.Listener {
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        Button button_search = (Button) findViewById(R.id.button_main_search);
        button_search.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
         
               
 
                String Keyword =  mEditTextSearchKeyword.getText().toString();
                mEditTextSearchKeyword.setText("");
 
                Intent intent = new Intent(MainActivity.this,SecondActivity.class);
                startActivity(intent);
 
                task = new GetData(this);
                task.execute("http://"+IP_ADDRESS+"/query.php",Keyword);
 
            }
        });
    }
}

@Override
public void onSuccess() {

}

@Override
public  void onFailure() {

}

}

 

spark (227,530 포인트) 님이 2021년 5월 18일 답변
갸갸님이 2021년 5월 18일 채택됨
소중한 답변 감사합니다! 안드로이드에 대해 아직 많이 모르는 단계라 막막했는데 배워갑니다!
저 혹시 AsyncTask는 MainActivity쪽에서 다루는게 코드 상 더 안전할까요?
코드가 더 깔끔해지고 유지보수하기 좋아지도록 하려면 역할이 다른 건 분리하시는 게 좋습니다. AsyncTask와 Activity는 서로 역할이 다르죠. AsyncTask는 API를 호출해서 데이터를 가져오는 역할을 하고 Acvitiy는 AsyncTask에서 가져온 데이터를 화면에 출력하는 역할을 합니다. 이렇게 함으로써 코드의 수정이 생길 때 건드려야 할 부분이 적어지고 테스트도 더 쉬워집니다. 참고로 안드로이드 11부터는 AsyncTask는  deprecated되었습니다. RxJava나 Kotlin coroutines 같은 걸 대신 사용하세요.
아하 그렇군요!! 좋은 답변 감사드립니다!
아 그래서 AsyncTask를 쓰면 밑줄이 그어졌던 것이로군요! 말씀 주신RxJava나 Kotlin coroutines를 써보도록 하겠습니다!
...