Window leak due to alert dialog

给你一囗甜甜゛ 提交于 2019-12-13 02:37:43

问题


Quite new in Android development, I keep getting a window leak exception, probably due to use of an alertbox I made. In searching for what I have to change, I tried a bunch of things and I can't find my error. Maybe someone can help me look through my code?

public class LogInActivity extends Activity {
    EditText gebruikersnaamET, paswoordET;
    TextView titel;
    TextView gebruikersnaamTV;
    TextView paswoordTV;
    TextView geenAccount;
    Button ok;
    String url = "";
    final Context context = this;
    String username = "";
    SharedPreferences settings;
    AlertBox alert;
    Gebruiker g = null;
    private ProgressDialog pDialog;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // http://stackoverflow.com/questions/4544302/android-prevent-user-from-coming-back-to-login-page-after-logging-in
        settings = context.getSharedPreferences("CoNeePrefs", 0);
        boolean isLogged = settings.getBoolean("isLogged", false);

        setTitle("Log in");
        setContentView(R.layout.activity_log_in);

        gebruikersnaamET = (EditText) findViewById(R.id.et_un);
        gebruikersnaamET.requestFocus();
        gebruikersnaamET.setTypeface(MyFonts.Fonts.PRESSTART);

        paswoordET = (EditText) findViewById(R.id.et_pw);
        paswoordET.setTypeface(MyFonts.Fonts.PRESSTART);

        ok = (Button) findViewById(R.id.btn_login);
        ok.setTypeface(MyFonts.Fonts.PRESSTART);

        titel = (TextView) findViewById(R.id.titel);
        // titel.setTypeface(MyFonts.Fonts.PRESSTART);
        Typeface face;
        face = Typeface.createFromAsset(getAssets(), "fonts/pressstart.ttf");
        titel.setTypeface(face);

        gebruikersnaamTV = (TextView) findViewById(R.id.tv_un);
        gebruikersnaamTV.setTypeface(MyFonts.Fonts.PRESSTART);

        paswoordTV = (TextView) findViewById(R.id.tv_pw);
        paswoordTV.setTypeface(MyFonts.Fonts.PRESSTART);

        geenAccount = (TextView) findViewById(R.id.nogGeenAccount);
        geenAccount.setTypeface(MyFonts.Fonts.PRESSTART);

        g = new Gebruiker();

        if (isLogged) {
            Intent intent = new Intent(context, MenuActivity.class);
            intent.putExtra("gebruikersnaam",
                    settings.getString("gebruikersnaam", "none"));
            startActivity(intent);
            finish();
        } else {
            ok.setOnClickListener(new View.OnClickListener() {

                @Override
                public void onClick(View v) {
                    // TODO Auto-generated method stub

                    new checkUserDetails().execute();
                }
            });

        }

        geenAccount.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View arg0) {
                Intent intent = new Intent(context, RegisterActivity.class);
                startActivity(intent);
                finish();
            }
        });

    }

    // http://www.androidhive.info/2012/05/how-to-connect-android-with-php-mysql/
    class checkUserDetails extends AsyncTask<String, String, String> {

        /**
         * Before starting background thread Show Progress Dialog
         * */
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            pDialog = new ProgressDialog(LogInActivity.this);
            pDialog.setMessage("In aan het loggen...");
            pDialog.setIndeterminate(false);
            pDialog.setCancelable(true);
            pDialog.show();
        }

        /**
         * Getting product details in background thread
         * */
        protected String doInBackground(String... params) {

            url = "http://iwtsl.ehb.be/~iris.vdz/check.php";
            ArrayList<NameValuePair> postParameters = new ArrayList<NameValuePair>();
            postParameters.add(new BasicNameValuePair("gebruikersnaam",
                    gebruikersnaamET.getText().toString()));
            postParameters.add(new BasicNameValuePair("paswoord", paswoordET
                    .getText().toString()));
            // String valid = "1";
            String res = null;
            String username = gebruikersnaamET.getText().toString();

            try {
                res = DatabaseAccess.getInstance().phpUitvoeren(postParameters,
                        url);

                if (res.equals("1")) {
                    g = DatabaseAccess.getInstance().getUser(username);
                    String adres = g.getStraat() + " - " + g.getPostcode()
                            + " " + g.getGemeente();
                    String volledigeNaam = g.getVoornaam() + " " + g.getNaam();
                    settings = context.getSharedPreferences("CoNeePrefs", 0);
                    SharedPreferences.Editor editor = settings.edit();
                    editor.putBoolean("isLogged", true);
                    editor.putString("gebruikersnaam", g.getGebruikersnaam());
                    editor.putString("naam", volledigeNaam);
                    editor.putString("e-mail", g.getEmail());
                    editor.putString("adres", adres);
                    editor.putString("paswoord",
                            g.getEncodedPaswoord(g.getPaswoord()));
                    editor.commit();

                    Intent intent = new Intent(context, MenuActivity.class);
                    startActivity(intent);
                    finish();
                } else {
                    alert = new AlertBox(context, "Error",
                            "Er is iets misgegaan, probeer opnieuw!\nMogelijke redenen:\n"
                                    + "- u heeft geen internetverbinding\n"
                                    + "- u heeft geen juiste login ingegeven\n"
                                    + "- er is een probleem met het netwerk\n"
                                    + "- er is een probleem met de database");
                }

            } catch (Exception e) {
                alert = new AlertBox(context, "Error", e.toString());

            }

            return null;
        }

        /**
         * After completing background task Dismiss the progress dialog
         * **/
        protected void onPostExecute(String file_url) {
            // dismiss the dialog once got all details
            pDialog.dismiss();
        }
    }

This is the code for the AlertBox:

public class AlertBox {

    public AlertBox(Context context, String title, String mymessage){
         new AlertDialog.Builder(context)
          .setMessage(mymessage)
          .setTitle(title)
          .setCancelable(true)
          .setNeutralButton(android.R.string.cancel,
             new DialogInterface.OnClickListener() {
             public void onClick(DialogInterface dialog, int whichButton){

             }})
          .show();
    }
}

this is the stack-trace i'm getting:

04-07 14:31:28.230: E/AndroidRuntime(10287): FATAL EXCEPTION: AsyncTask #1
04-07 14:31:28.230: E/AndroidRuntime(10287): java.lang.RuntimeException: An error occured while executing doInBackground()
04-07 14:31:28.230: E/AndroidRuntime(10287):    at android.os.AsyncTask$3.done(AsyncTask.java:200)
04-07 14:31:28.230: E/AndroidRuntime(10287):    at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:274)
04-07 14:31:28.230: E/AndroidRuntime(10287):    at java.util.concurrent.FutureTask.setException(FutureTask.java:125)
04-07 14:31:28.230: E/AndroidRuntime(10287):    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:308)
04-07 14:31:28.230: E/AndroidRuntime(10287):    at java.util.concurrent.FutureTask.run(FutureTask.java:138)
04-07 14:31:28.230: E/AndroidRuntime(10287):    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1088)
04-07 14:31:28.230: E/AndroidRuntime(10287):    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:581)
04-07 14:31:28.230: E/AndroidRuntime(10287):    at java.lang.Thread.run(Thread.java:1019)
04-07 14:31:28.230: E/AndroidRuntime(10287): Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
04-07 14:31:28.230: E/AndroidRuntime(10287):    at android.os.Handler.(Handler.java:121)
04-07 14:31:28.230: E/AndroidRuntime(10287):    at android.app.Dialog.(Dialog.java:101)
04-07 14:31:28.230: E/AndroidRuntime(10287):    at android.app.AlertDialog.(AlertDialog.java:63)
04-07 14:31:28.230: E/AndroidRuntime(10287):    at android.app.AlertDialog$Builder.create(AlertDialog.java:797)
04-07 14:31:28.230: E/AndroidRuntime(10287):    at android.app.AlertDialog$Builder.show(AlertDialog.java:812)
04-07 14:31:28.230: E/AndroidRuntime(10287):    at be.iwt.ehb.conee.extrafeatures.AlertBox.(AlertBox.java:20)
04-07 14:31:28.230: E/AndroidRuntime(10287):    at be.iwt.ehb.conee.activities.LogInActivity$checkUserDetails.doInBackground(LogInActivity.java:178)
04-07 14:31:28.230: E/AndroidRuntime(10287):    at be.iwt.ehb.conee.activities.LogInActivity$checkUserDetails.doInBackground(LogInActivity.java:1)
04-07 14:31:28.230: E/AndroidRuntime(10287):    at android.os.AsyncTask$2.call(AsyncTask.java:185)
04-07 14:31:28.230: E/AndroidRuntime(10287):    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:306)
04-07 14:31:28.230: E/AndroidRuntime(10287):    ... 4 more
04-07 14:31:28.661: W/IInputConnectionWrapper(10287): showStatusIcon on inactive InputConnection
04-07 14:31:28.681: D/dalvikvm(10287): GC_CONCURRENT freed 200K, 49% free 2915K/5639K, external 303K/558K, paused 18ms+62ms
04-07 14:31:29.381: E/WindowManager(10287): Activity be.iwt.ehb.conee.activities.LogInActivity has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView@40538cb0 that was originally added here
04-07 14:31:29.381: E/WindowManager(10287): android.view.WindowLeaked: Activity be.iwt.ehb.conee.activities.LogInActivity has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView@40538cb0 that was originally added here
04-07 14:31:29.381: E/WindowManager(10287):     at android.view.ViewRoot.(ViewRoot.java:259)
04-07 14:31:29.381: E/WindowManager(10287):     at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:148)
04-07 14:31:29.381: E/WindowManager(10287):     at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:91)
04-07 14:31:29.381: E/WindowManager(10287):     at android.view.Window$LocalWindowManager.addView(Window.java:465)
04-07 14:31:29.381: E/WindowManager(10287):     at android.app.Dialog.show(Dialog.java:241)
04-07 14:31:29.381: E/WindowManager(10287):     at be.iwt.ehb.conee.activities.LogInActivity$checkUserDetails.onPreExecute(LogInActivity.java:127)
04-07 14:31:29.381: E/WindowManager(10287):     at android.os.AsyncTask.execute(AsyncTask.java:391)
04-07 14:31:29.381: E/WindowManager(10287):     at be.iwt.ehb.conee.activities.LogInActivity$1.onClick(LogInActivity.java:96)
04-07 14:31:29.381: E/WindowManager(10287):     at android.view.View.performClick(View.java:2506)
04-07 14:31:29.381: E/WindowManager(10287):     at android.view.View$PerformClick.run(View.java:9112)
04-07 14:31:29.381: E/WindowManager(10287):     at android.os.Handler.handleCallback(Handler.java:587)
04-07 14:31:29.381: E/WindowManager(10287):     at android.os.Handler.dispatchMessage(Handler.java:92)
04-07 14:31:29.381: E/WindowManager(10287):     at android.os.Looper.loop(Looper.java:130)
04-07 14:31:29.381: E/WindowManager(10287):     at android.app.ActivityThread.main(ActivityThread.java:3835)
04-07 14:31:29.381: E/WindowManager(10287):     at java.lang.reflect.Method.invokeNative(Native Method)
04-07 14:31:29.381: E/WindowManager(10287):     at java.lang.reflect.Method.invoke(Method.java:507)
04-07 14:31:29.381: E/WindowManager(10287):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:864)
04-07 14:31:29.381: E/WindowManager(10287):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:622)
04-07 14:31:29.381: E/WindowManager(10287):     at dalvik.system.NativeStart.main(Native Method)

Thanks a lot in advance!


回答1:


The window leak is not the root cause of your crash; the primary problem here is that you're trying to create a dialog from a background thread:

Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()

In AlertBox, you're creating a new dialog, which in turn contain their own Handler:

new AlertDialog.Builder(context)
          [...]
          .show();

However, you're creating AlertBox from your AsyncTask's doInBackground():

new AlertBox(context, "Error", e.toString());

Move that logic into the main thread, for instance by handling the error in onPostExecute().

Secondarily, you're getting the "window leaked" message because the AsyncTask is still running while the activity is gone, and it contains references to objects attached to that window, specifically pDialog.



来源:https://stackoverflow.com/questions/15862569/window-leak-due-to-alert-dialog

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!