컨텍스트로 getApplication ()을 사용하여 "창을 추가 할 수 없습니다. 토큰 null은 응용 프로그램에 대한 것이 아닙니다."를 표시하는 대화 상자
내 활동이 매개 변수로 컨텍스트가 필요한 AlertDialog를 작성하려고합니다. 다음을 사용하면 예상대로 작동합니다.
AlertDialog.Builder builder = new AlertDialog.Builder(this);
그러나 화면 회전과 같은 단순한 작업 중에도 Activity가 파괴되고 다시 생성 될 때 메모리 누수가 발생할 가능성이 있기 때문에 컨텍스트로 "this"를 사용하는 것이 조심 스럽습니다. A로부터 안드로이드 개발자 블로그에 관련 포스트 :
컨텍스트 관련 메모리 누수를 방지하는 두 가지 쉬운 방법이 있습니다. 가장 분명한 것은 컨텍스트를 자신의 범위 밖에서 벗어나지 않는 것입니다. 위의 예는 정적 참조의 경우를 보여 주었지만 내부 클래스와 외부 클래스에 대한 암시 적 참조는 똑같이 위험 할 수 있습니다. 두 번째 해결책은 애플리케이션 컨텍스트를 사용하는 것입니다. 이 컨텍스트는 애플리케이션이 활성 상태이고 활동 라이프 사이클에 의존하지 않는 한 지속됩니다. 컨텍스트가 필요한 수명이 긴 개체를 유지하려는 경우 응용 프로그램 개체를 기억하십시오. Context.getApplicationContext () 또는 Activity.getApplication ()을 호출하여 쉽게 얻을 수 있습니다.
그러나 예외가 발생 하므로 AlertDialog()
둘 다 getApplicationContext()
또는 getApplication()
컨텍스트로 허용 되지 않습니다 .
"창을 추가 할 수 없습니다. 토큰 null은 응용 프로그램 용이 아닙니다."
그렇다면 우리가 공식적으로 사용하도록 권고 Activity.getApplication()
되었지만 광고 된대로 작동하지 않기 때문에 이것이 정말로 "버그"로 간주되어야 합니까?
짐
대신에 getApplicationContext()
, 단지 사용 ActivityName.this
.
사용 this
은 나를 위해 작동하지 않았지만 작동했습니다 MyActivityName.this
. 이것이 this
일 을 할 수없는 사람에게 도움이되기를 바랍니다 .
을 계속 사용할 수 getApplicationContext()
있지만 사용하기 전에 다음 플래그를 추가해야합니다. dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT)
, 그러면 오류가 표시되지 않습니다.
매니페스트에 다음 권한을 추가합니다.
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
대화 상자는 "컨텍스트가 필요한 수명이 긴 개체"가 아니어야합니다. 설명서가 혼란 스럽습니다. 기본적으로 다음과 같이하면 :
static Dialog sDialog;
( 정적 참고 )
그런 다음 어딘가에서 한 활동에서
sDialog = new Dialog(this);
활동을 파괴하는 회전 또는 이와 유사한 동안 원래 활동이 누출 될 수 있습니다. (onDestroy에서 정리하지 않는 한,이 경우 Dialog 객체를 정적으로 만들지 않을 것입니다)
일부 데이터 구조의 경우 애플리케이션의 컨텍스트를 기반으로 정적으로 만드는 것이 합리적이지만 일반적으로 대화 상자와 같은 UI 관련 항목에는 적합하지 않습니다. 그래서 다음과 같이 :
Dialog mDialog;
...
mDialog = new Dialog(this);
mDialog는 정적이 아니기 때문에 활동과 함께 해제되므로 문제가 없으며 활동을 누출해서는 안됩니다.
"... AlertDialog ()에 대해 getApplicationContext () 또는 getApplication () 둘 다 컨텍스트로 허용되지 않는다고 말했을 때 문제를 올바르게 식별 한 것입니다. '창을 추가 할 수 없습니다. 지원서'"
대화 상자를 만들려면 응용 프로그램 컨텍스트가 아닌 활동 컨텍스트 또는 서비스 컨텍스트 가 필요합니다 (getApplicationContext () 및 getApplication () 모두 응용 프로그램 컨텍스트를 반환 함).
활동 컨텍스트 를 얻는 방법은 다음과 같습니다 .
(1) 활동 또는 서비스에서 :
AlertDialog.Builder builder = new AlertDialog.Builder(this);
(2) 조각에서 : AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
메모리 누수는 객체가 자신에 대한 참조 (즉, 객체의 데이터를 저장하기 위해 실제로 할당 된 메모리에 대한 참조) 인 "this"참조에 내재 된 문제가 아닙니다. 그것은 일어나는 모든 가비지 콜렉터 (GC)가 할당 된 메모리가 유용한 수명을 지났다 후 확보 할 수없는있는 할당 된 메모리.
Most of the time, when a variable goes out of scope, the memory will be reclaimed by the GC. However, memory leaks can occur when the reference to an object held by a variable, say "x", persists even after the object has outlived its useful lifespan. The allocated memory will hence be lost for as long as "x" holds a reference to it because GC will not free up the memory for as long as that memory is still being referenced. Sometimes, memory leaks are not apparent because of a chain of references to the allocated memory. In such a case, the GC will not free up the memory until all references to that memory have been removed.
To prevent memory leaks, check your code for logical errors that cause allocated memory to be referenced indefinitely by "this" (or other references). Remember to check for chain references as well. Here are some tools you can use to help you analyze memory use and find those pesky memory leaks:
I had to send my context through a constructor on a custom adapter displayed in a fragment and had this issue with getApplicationContext(). I solved it with:
this.getActivity().getWindow().getContext()
in the fragments' onCreate
callback.
in Activity just use:
MyActivity.this
in Fragment:
getActivity();
In Activity
on click of button showing a dialog box
Dialog dialog = new Dialog(MyActivity.this);
Worked for me.
Little hack: you can prevent destroying your activity by GC (you should not do it, but it can help in some situations. Don't forget to set contextForDialog
to null
when it's no longer needed):
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();
}
...
}
***** kotlin version *****
You should pass this@YourActivity
instead of applicationContext
or baseContext
If you are using a fragment and using AlertDialog/Toast message then use getActivity() in the context parameter.
like this
ProgressDialog pdialog;
pdialog = new ProgressDialog(getActivity());
pdialog.setCancelable(true);
pdialog.setMessage("Loading ....");
pdialog.show();
adding
dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
and
"android.permission.SYSTEM_ALERT_WINDOW"/>
in manifest
It works for me now. After even close and open the application, gave me the error at that time.
I was using ProgressDialog
in a fragment and was getting this error on passing getActivity().getApplicationContext()
as the constructor parameter. Changing it to getActivity().getBaseContext()
didn't work either.
The solution that worked for me was to pass getActivity()
; i.e.
progressDialog = new ProgressDialog(getActivity());
Use MyDialog md = new MyDialog(MyActivity.this.getParent());
If you are outside of the Activity then you need to use in your function "NameOfMyActivity.this" as Activity activity, example:
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);
If you are using a fragment and using an AlertDialog / Toast
message, use getActivity()
in the context parameter.
Worked for me.
Cheers!
Try to use the context of an activity which will be under the dialog. But be carefull when you use "this" keyword, because it will not work everytime.
Forexample, if you have TabActivity as host with two tabs, and each tab is another activity, and if you try to create dialog from one of the tabs (activities) and if you use "this", then you will get exception, In this case dialog should be connected to host activity which host everything and visible. (you can say most visible parent Activity's context)
I did not find this info from any document but by trying. This is my solution without strong background, If anybody with better knownledge, feel free to comment.
For future readers, this should help:
public void show() {
if(mContext instanceof Activity) {
Activity activity = (Activity) mContext;
if (!activity.isFinishing() && !activity.isDestroyed()) {
dialog.show();
}
}
}
In my case work:
this.getContext();
Or another possibility is to create Dialog as follow:
final Dialog dialog = new Dialog(new ContextThemeWrapper(
this, R.style.MyThemeDialog));
I think it may happen as well if you are trying to show a dialog from a thread which is not the main UI thread.
Use runOnUiThread()
in that case.
Try getParent()
at the argument place of context like new AlertDialog.Builder(getParent());
Hope it will work, it worked for me.
After taking a look at the API, you can pass the dialog your activity or getActivity if you're in a fragment, then forcefully clean it up with dialog.dismiss() in the return methods to prevent leaks.
Though it is not explicitly stated anywhere I know, it seems you are passed back the dialog in the OnClickHandlers just to do this.
Here is how I resolved same error for my application:
Adding the following line after creating the dialog:
dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG);
You will not need to acquire a context. This is particularly useful if you are popping up another dialog over current popped up dialog. Or when it's not convenient to get a context.
Hope this can help you with your app development.
David
If your Dialog is creating on the adapter:
Pass the Activity to the Adapter Constructor:
adapter = new MyAdapter(getActivity(),data);
Receive on the Adapter:
public MyAdapter(Activity activity, List<Data> dataList){
this.activity = activity;
}
Now you can use on your Builder
AlertDialog.Builder alert = new AlertDialog.Builder(activity);
android.support.v7.app.AlertDialog.Builder builder = new android.support.v7.app.AlertDialog.Builder(getWindow().getDecorView().getRootView().getContext());
builder.setTitle("Confirm");
builder.setMessage("Are you sure you want delete your old account?");
builder.setPositiveButton("YES", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
//Do nothing but close the dialog
dialog.dismiss();
}
});
builder.setNegativeButton("NO", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
//Do nothing
dialog.dismiss();
}
});
android.support.v7.app.AlertDialog alert = builder.create();
alert.show();
'IT박스' 카테고리의 다른 글
파이썬에서 여러 생성자를 갖는 깔끔하고 파이썬적인 방법은 무엇입니까? (0) | 2020.10.02 |
---|---|
ASP.NET MVC의 열거 형에서 드롭 다운 목록을 만드는 방법은 무엇입니까? (0) | 2020.10.02 |
os / path 형식에 관계없이 경로에서 파일 이름 추출 (0) | 2020.10.02 |
Spring Framework에서 @Inject와 @Autowired의 차이점은 무엇입니까? (0) | 2020.10.02 |
PHP를 사용한 jQuery Ajax POST 예제 (0) | 2020.10.02 |