android alertdialog reference




Dialog throwing "창을 추가 할 수 없습니다-응용 프로그램에 대한 토큰 null이 아닙니다"getApplication()이 컨텍스트로 표시됨 (16)

활동 또는 서비스 가 아닌 컨텍스트 를 통해 응용 프로그램 window/dialog 를 표시 할 수 없습니다. 유효한 활동 참조를 전달하십시오.

내 활동이 컨텍스트를 매개 변수로 요구하는 AlertDialog를 만들려고합니다. 내가 사용하면 예상대로 작동합니다.

AlertDialog.Builder builder = new AlertDialog.Builder(this);

그러나 나는 화면 누름과 같은 간단한 작업 중에도 Activity가 파괴되어 다시 생성 될 때 메모리 누수 가능성으로 인해 "this"를 컨텍스트로 사용하는 것에 신경 쓰지 않습니다. Android 개발자 블로그의 관련 게시물에서

문맥 관련 메모리 누수를 피하는 두 가지 쉬운 방법이 있습니다. 가장 확실한 방법은 자체 범위 밖에서 컨텍스트를 벗어나는 것을 피하는 것입니다. 위의 예는 정적 참조의 경우를 보여 주지만 내부 클래스와 외부 클래스에 대한 암시 적 참조는 똑같이 위험 할 수 있습니다. 두 번째 해결 방법은 Application 컨텍스트를 사용하는 것입니다. 이 컨텍스트는 애플리케이션이 살아 있고 활동 라이프 사이클에 의존하지 않는 한 계속 존재합니다. 컨텍스트가 필요한 수명이 긴 개체를 유지하려는 경우 응용 프로그램 개체를 기억하십시오. Context.getApplicationContext () 또는 Activity.getApplication ()을 호출하면 쉽게 얻을 수 있습니다.

하지만 AlertDialog() getApplicationContext() 또는 getApplication() 도 예외로 throw되므로 Context로 사용할 수 없습니다.

"창을 추가 할 수 없습니다 - 응용 프로그램에 대한 토큰 Null이 아닙니다"

참고 문헌 당 1 , 2 , 3 등.

그래서 우리가 공식적으로 Activity.getApplication() 을 사용하도록 권고 받았지만 아직 광고 된대로 작동하지 않기 때문에 이것이 실제로 "버그"로 간주되어야합니까?


***** kotlin 버전 *****

[email protected]applicationContext 또는 baseContext 대신 전달해야합니다.


API를 살펴본 후, 프래그먼트에 있다면 액티비티 또는 getActivity 대화 상자를 전달한 다음 누출을 방지하기 위해 리턴 메소드에서 dialog.dismiss ()를 사용하여 강제로 제거 할 수 있습니다.

내가 아는 곳에 명시 적으로 명시되지는 않았지만, 이것을하기 위해 OnClickHandlers의 대화 상자로 다시 전달되는 것 같습니다.


기본 UI 스레드가 아닌 스레드에서 대화 상자를 표시하려고하는 경우에도 문제가 발생할 수 있습니다.

이 경우 runOnUiThread() 를 사용하십시오.


대화 상자 아래에있을 활동의 컨텍스트를 사용해보십시오. 그러나 매번 작동하지 않으므로 "this"키워드를 사용할 때는주의하십시오.

예를 들어, 두 개의 탭이있는 호스트로 TabActivity가 있고 각 탭이 다른 활동 인 경우 탭 중 하나 (대화 상자)에서 대화 상자를 만들려고하고 "this"를 사용하면 예외가 발생합니다. 사례 대화는 모든 것을 호스트하고 가시화하는 호스트 활동에 연결되어야합니다. (가장 눈에 띄는 상위 액티비티의 컨텍스트를 말할 수 있음)

어떤 문서에서나이 정보를 찾지는 않았지만 시도했습니다. 이것은 강한 배경이없는 해결책입니다. 더 잘 알려진 사람이라면 누구나 자유롭게 의견을 말할 수 있습니다.


대화 상자는 "컨텍스트가 필요한 수명이 긴 개체"가 아니어야합니다. 설명서가 혼란 스럽습니다. 기본적으로 다음과 같이하면 :

static Dialog sDialog;

( 정적 참고)

그런 다음 어딘가에서 한 활동에서

 sDialog = new Dialog(this);

교대 또는 유사한 활동 중에 원래 활동이 누출 될 가능성이 있습니다. (onDestroy를 정리하지 않는 한 Dialog 객체를 정적으로 만들지는 않을 것입니다.)

일부 데이터 구조의 경우 정적 및 응용 프로그램의 컨텍스트를 기반으로하는 것이 좋지만 일반적으로 대화 상자와 같은 UI 관련 작업에는 적합하지 않습니다. 이렇게 뭔가 :

Dialog mDialog;

...

mDialog = new Dialog(this);

정적이어서 mDialog가 액티비티와 함께 ​​해제되므로 액티비티가 누출되지 않아야합니다.


또는 또 다른 가능성은 Dialog를 다음과 같이 생성하는 것입니다.

final Dialog dialog = new Dialog(new ContextThemeWrapper(
            this, R.style.MyThemeDialog));

미래의 독자들에게 이것은 도움이 될 것입니다 :

public void show() {
    if(mContext instanceof Activity) {
        Activity activity = (Activity) mContext;
        if (!activity.isFinishing() && !activity.isDestroyed()) {
            dialog.show();
        }
    }
}

약간의 해킹 : GC로 활동을 파괴하는 것을 막을 수 있습니다 (물론 해선 안되지만 상황에 따라 도움이 될 수 있습니다).

public class PostActivity extends Activity  {
    ...
    private Context contextForDialog = null;
    ...
    public void onCreate(Bundle savedInstanceState) {
        ...
        contextForDialog = this;
    }
    ...
    private void showAnimatedDialog() {
        mSpinner = new Dialog(contextForDialog);
        mSpinner.setContentView(new MySpinner(contextForDialog));
        mSpinner.show();
    }
    ...
}

이 기능을 사용 this MyActivityName.this 가 작동하지 않습니다. 희망이이 일을 얻을 수없는 사람을 도와줍니다.


프래그먼트를 사용하고 AlertDialog / Toast 메시지를 사용하는 경우 context 매개 변수에서 getActivity() 를 사용하십시오.

나를 위해 일했다.

건배!


프래그먼트를 사용하고 AlertDialog / Toast 메시지를 사용하는 경우 context 매개 변수에서 getActivity ()를 사용하십시오.

이렇게

ProgressDialog pdialog;
pdialog = new ProgressDialog(getActivity());
pdialog.setCancelable(true);
pdialog.setMessage("Loading ....");
pdialog.show();

프래그먼트에서 ProgressDialog 를 사용하고 getActivity().getApplicationContext() 를 생성자 매개 변수로 전달할 때이 오류가 발생했습니다. 그것을 getActivity().getBaseContext() 변경해도 작동하지 않았습니다.

나를 위해 일한 해결책은 getActivity() 를 전달하는 것이 었습니다. 즉

progressDialog = new ProgressDialog(getActivity());


활동 외부에있는 경우 "NameOfMyActivity.this"기능을 활동 활동으로 사용해야합니다 (예 :

public static void showDialog(Activity activity) {
        AlertDialog.Builder builder = new AlertDialog.Builder(activity);
        builder.setMessage("Your Message")
        .setPositiveButton("Yes", dialogClickListener)
        .setNegativeButton("No", dialogClickListener).show();
}


//Outside your Activity
showDialog(NameOfMyActivity.this);

getApplicationContext() 계속 사용할 수 있지만 사용하기 전에이 플래그를 추가해야합니다 : dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT) , 오류가 표시되지 않습니다.

매니페스트에 다음 권한을 추가하십시오.

<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />

getApplicationContext() 대신 ActivityName.this 사용하십시오.





builder