0

저는 비동기 작업에 상당히 익숙하지 않지만 클래스 레벨 변수에 액세스하는 내 응용 프로그램 용으로 만든 몇 가지 항목과 실제 ​​장치에서 이러한 작업을 수행 할 때 doInBackground()에서 몇 가지 null 포인터 예외가 발생했습니다.Android - 비동기 작업에서 클래스 수준 변수에 액세스하는 것은 잘못된가요?

이 변수는 실제로 이러한 변수가 비동기 작업 내에서 액세스되어서는 안되며 대신 생성자 또는 매개 변수를 통해 전달되어야한다고 생각합니다. 예를 들어 액티비티 B로 전환하고 비동기 작업이 활동 A, A의 모든 변수는 null이되어야합니다.

그리고 이러한 변수에 액세스하는 것이 비동기 작업의 컨텍스트 내에서 절대 사용되어서는 안되는 경우 IDE (내 케이스의 Android Studio)가 위험한 행동이라고 경고하지 않아야합니까?

편집 : 너무 빨리 도움이됩니다. 다행히도 이것은 미래에 다른 사람들을 도울 것입니다.

public class MyActivity extends ActionBarActivity { 

private Context mContext; 
private User mUser; 
private ProgressDialog mProgressDialog; 

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    mContext = this; 
    mProgressDialog = new ProgressDialog(mContext); 
    mUser = new User(); 
    new MyAsyncTask.execute(); 
} 


private class MyAsyncTask extends AsyncTask<Params, Integer, Void> { 

    @Override 
    protected void onPreExecute() { 
     super.onPreExecute(); 
     mProgressDialog.setIndeterminate(true); 
     mProgressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER); 
     mProgressDialog.setCancelable(true); 
     mProgressDialog.setMessage("My message"); 
     mProgressDialog.show(); 
    } 

    @Override 
    protected void onProgressUpdate(Integer... progress) { 
     super.onProgressUpdate(progress); 
    } 

    @Override 
    protected Void doInBackground(Params... params) { 
     Toast.makeText(mContext, "In doInBackground()", Toast.LENGTH_LONG).show(); 
     mUser.someMethodThatTakesTime(); 
     return null; 
    } 

    @Override 
    protected void onPostExecute(Void params) { 
     mProgressDialog.dismiss(); 
     //Possibly launch another activity 
    } 
} 
} 
+0

스레드를 통해 올바르게 액세스하는 한 이러한 변수에 액세스하는 것이 완전히 괜찮은 경우가 있습니다. 귀하의 질문의 구체적인 감안할 때, 나는 당신의 생성자에 변수를 전달 향해 기댈 것입니다,하지만 당신이 관련 코드를 게시 한 후 최선의 추천 올 것이라고 생각합니다. – Phil

+0

이 질문은 당신에게 유용 할 것이라고 생각합니다. http://stackoverflow.com/questions/154551/volatile-vs-interlocked-vs-lock?rq=1 – CurlyPaul

답변

1

당신은 확실히 당신의 활동에 내부 클래스로서 AsyncTask을 사용하지 않아야합니다 : 여기에 대해 생각했다 대략 무엇을하는 일부 코드입니다. 내부 클래스에는 컨테이너 클래스에 대한 암시 적 강력한 참조가 포함되어 있으므로 Activity Lifecycle 중 경험 한 것처럼 널 포인터를 가져올 위험이 있습니다. 그리고 B 액티비티가 A 액티비티 위로 올라간다면 그것은 발생하지 않습니다. 또한 디바이스를 회전 시키면 발생할 수 있습니다.

문제는 활동주기입니다 (IDE에서 경고하지 않는 이유입니다). 구성 변경 (예 : 회전) 또는 메모리 부족 상황에서 활동을 파괴하고 다시 만들 수 있습니다. 하지만 AsyncTask는 여전히 이전 활동과 연결됩니다.

이것에 대해 스레드가 많이 있습니다

https://github.com/stephanenicolas/robospice

:

https://stackoverflow.com/a/8550351/1856960

https://stackoverflow.com/a/16305144/1856960

당신은이 처리하도록 설계된 타사 프레임 워크로 볼 수 Google은 더 많은 정보를 제공하기 위해 거의 모든 목록을 제공하지 않습니다.

관련 문제