当前位置: 首页 > 知识库问答 >
问题:

Android.View.WindowLeaked-AlerDialog生成器

丰智
2023-03-14

我有一个activity,其中用户被发送到设备设置,如果GPS关闭,以打开它,当用户从设置回来,然后设备是请求位置许可。

第一个GPS对话框是通过AlertDialog builder完成的,下面是我的完整代码:

      public class Okoli extends AppCompatActivity implements LocationListener {

    private final static int ALL_PERMISSIONS_RESULT = 101;
    private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 1;
    private static final long MIN_TIME_BW_UPDATES = 90000; //1.5 mins

    LocationManager locationManager;
    Location loc;
    ArrayList<String> permissions = new ArrayList<>();
    ArrayList<String> permissionsToRequest= new ArrayList<>();
    ArrayList<String> permissionsRejected = new ArrayList<>();
    boolean isGPS = false;
    boolean isNetwork = false;
    boolean canGetLocation = true;

    ArrayList<Actors> actorsList;
    ActorAdapterDist adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        if(getSupportActionBar() != null){
            getSupportActionBar().setDisplayHomeAsUpEnabled(true);
            getSupportActionBar().setHomeButtonEnabled(true);
            getSupportActionBar().setTitle((Html.fromHtml("<font color=\"#c6c6c6\">V okolí (vzdušná čiara)</font>")));
            getSupportActionBar().setHomeAsUpIndicator(R.drawable.back);
        }

        setContentView(R.layout.okoli_fragment);

        actorsList = new ArrayList<>();
        adapter = new ActorAdapterDist(this, R.layout.okoli_item, actorsList);
        TextView listTitle = findViewById(R.id.booklist_title1);
        listTitle.setText("Čakám na signál GPS");

        getIntent().setAction("created");
        String MY_PREFS_NAME = "resumecheck";
        SharedPreferences.Editor editor = getSharedPreferences(MY_PREFS_NAME, MODE_PRIVATE).edit();
        editor.putInt("idName", 2);
        editor.apply();

        ListView lv = findViewById(R.id.listViewx);   lv.setAdapter(adapter);

        locationManager = (LocationManager) this.getSystemService(Service.LOCATION_SERVICE);
        assert locationManager != null;
        isGPS = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
        isNetwork = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);

        permissions.add(Manifest.permission.ACCESS_FINE_LOCATION);
        permissions.add(Manifest.permission.ACCESS_COARSE_LOCATION);
        permissionsToRequest = findUnAskedPermissions(permissions);

        if (!isGPS && !isNetwork) {

            showSettingsAlert(getString(R.string.askgps),  new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {

                    if (dialog != null) {
                        dialog.dismiss();  dialog = null;
                    }
                    Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
                    startActivity(intent);
                }
            });
            getLastLocation();
        } else {

            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                if (permissionsToRequest.size() > 0) {
                    requestPermissions(permissionsToRequest.toArray(new String[permissionsToRequest.size()]),
                            ALL_PERMISSIONS_RESULT);
                    canGetLocation = false;
                }
            }

            getLocation();
        }

    }

    @Override
    public void onLocationChanged(Location location) {updateUI(location);}

    @Override
    public void onStatusChanged(String s, int i, Bundle bundle) {}

    @Override
    public void onProviderEnabled(String s) {
        getLocation();
    }

    @Override
    public void onProviderDisabled(String s) {
        if (locationManager != null) {
            locationManager.removeUpdates(this);
        }
    }

    private void getLocation() { SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);


        try {
            if (canGetLocation) {

                if (isGPS) {
                    locationManager.requestLocationUpdates(
                            LocationManager.GPS_PROVIDER,
                            MIN_TIME_BW_UPDATES,
                            MIN_DISTANCE_CHANGE_FOR_UPDATES, this);

                    if (locationManager != null) {
                        loc = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
                        if (loc != null) {updateUI(loc);}
                    }

                } else if (isNetwork) {
                    // from Network Provider
                    locationManager.requestLocationUpdates(
                            LocationManager.NETWORK_PROVIDER,
                            MIN_TIME_BW_UPDATES,
                            MIN_DISTANCE_CHANGE_FOR_UPDATES, this);

                    if (locationManager != null) {
                        loc = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
                        if (loc != null) {updateUI(loc);}
                    }

                } else {
                    loc.setLatitude(0);
                    loc.setLongitude(0);
                    updateUI(loc);
                }

            } else {
                Toast.makeText(this, R.string.nolocation,
                        Toast.LENGTH_LONG).show();
            }
        } catch (SecurityException e) {
            e.printStackTrace();
        }
    }

    private void getLastLocation() {
        try {
            Criteria criteria = new Criteria();
            String provider = locationManager.getBestProvider(criteria, false);

            if(provider==null) {    showSettingsAlert(getString(R.string.askgps),  new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
                    startActivity(intent);
                }
            });}

            else {

                Location location = locationManager.getLastKnownLocation(provider);
                if (location != null) {updateUI(location);}

            }
        } catch (SecurityException e) {
            e.printStackTrace();
        }
    }

    private ArrayList findUnAskedPermissions(ArrayList<String> wanted) {
        ArrayList<String> result = new ArrayList<>();

        for (String perm : wanted) {
            if (!hasPermission(perm)) {
                result.add(perm);
            }
        }

        return result;
    }

    private boolean hasPermission(String permission) {
        if (canAskPermission()) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                return (this.checkSelfPermission(permission) == PackageManager.PERMISSION_GRANTED);
            }
        }
        return true;
    }

    private boolean canAskPermission() {
        return (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP_MR1);
    }

    @TargetApi(Build.VERSION_CODES.M)
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {


        switch (requestCode) {
            case ALL_PERMISSIONS_RESULT:

                for (String perms : permissionsToRequest) {
                    if (!hasPermission(perms)) {
                        permissionsRejected.add(perms);
                    }
                }

                if (permissionsRejected.size() > 0) {//Log.e("rejected", "onRequestPermissionsResult");

                 String MY_PREFS_NAME = "resumecheck";
                    SharedPreferences.Editor editor = getSharedPreferences(MY_PREFS_NAME, MODE_PRIVATE).edit();
                    editor.putInt("idName", 2);
                    editor.apply();


                                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                        if (shouldShowRequestPermissionRationale(permissionsRejected.get(0))) {


                            editor.putInt("idName", 1);
                            editor.apply();

                            showMessageOKCancel(getString(R.string.denied),
                                    new DialogInterface.OnClickListener() {
                                        @Override
                                        public void onClick(DialogInterface dialog, int which) {
                                            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                                                requestPermissions(permissionsRejected.toArray(
                                                        new String[permissionsRejected.size()]), ALL_PERMISSIONS_RESULT);
                                            }
                                        }
                                    });
                            return;
                        }
                    }
                } else {
                    // Log.e("ON", "No rejected permissions.");
                    String MY_PREFS_NAME = "resumecheck";
                    SharedPreferences.Editor editor = getSharedPreferences(MY_PREFS_NAME, MODE_PRIVATE).edit();
                    editor.putInt("idName", 2);
                    editor.apply();



                    canGetLocation = true;
                    getLocation();
                }
                break;
        }
    }

    public void showSettingsAlert(String message, DialogInterface.OnClickListener okListener) {

        AlertDialog.Builder builder = new AlertDialog.Builder(this, R.style.Theme_AppCompat_Dialog_Alert);
        builder.setTitle(R.string.nogps);
        builder.setMessage(message);
        builder.setPositiveButton(R.string.ano, okListener);
        builder.setNegativeButton(R.string.nie, null);
        builder.create();
        builder.show();

    }

    private void showMessageOKCancel(String message, DialogInterface.OnClickListener okListener) {

        new AlertDialog.Builder(this, R.style.Theme_AppCompat_Dialog_Alert)
                .setMessage(message)
                .setPositiveButton("OK", okListener)
                .setNegativeButton(R.string.cancel, null)
                .create()
                .show();
    }

    public void updateUI(Location loc) {
        double Act1=loc.getLatitude();
        double Act2=loc.getLongitude();
        adapter.clear();adapter.notifyDataSetChanged();

        TextView listTitle = findViewById(R.id.booklist_title1);
        ListView lv = findViewById(R.id.listViewx);

        if (Act1 > 0.0) { listTitle.setVisibility(View.GONE);lv.setVisibility(View.VISIBLE);GetContacts task = new GetContacts (Act1, Act2);
            task.execute();
            //  new GetContacts().execute(Act1,Act2);
        } else {
            listTitle.setVisibility(View.VISIBLE);listTitle.setText("Čakám na signál GPS");lv.setVisibility(View.GONE);
        }
    }

    ProgressDialog dialog;

    @Override
    public void onDestroy() {
        super.onDestroy();

        if (locationManager != null) {
            locationManager.removeUpdates(this);
        }
        if (dialog != null) {
            dialog.dismiss();
            dialog = null;
        }

    }

    @Override
    protected void onPause() {
        super.onPause();
        if (dialog != null) {
            dialog.dismiss();
            dialog = null;
        }
    }

    class GetContacts extends AsyncTask<Double, Void, Boolean> {


        private Double act1;
        private Double act2;

        GetContacts(double act1, double act2) {
            this.act1 = act1;
            this.act2 = act2;
        }


        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            dialog = new ProgressDialog(Okoli.this);
            dialog.setMessage("Načítavam");
            dialog.setTitle("Pripájam sa k serveru");
            dialog.show();
            dialog.setCancelable(false);
dialog.dismiss();
            dialog=null;
        }

        @Override
        protected Boolean doInBackground(Double... args) {
            HttpHandler sh = new HttpHandler();
            String url = "https://www.hrady-zamky.sk/app/premium_feed.php?i=7&search=";
            String jsonStr = sh.makeServiceCall(url);

            int pocet =0;

            if (jsonStr != null) {
                try {JSONObject jsonObj = new JSONObject(jsonStr);
                    JSONArray actors = jsonObj.getJSONArray("result");

                    double myDistx;
                    //Log.e("pocet",String.format("value = %d", actors.length()));

                    for (int i = 0; i < actors.length(); i++) {
                        JSONObject c = actors.getJSONObject(i);

                        Actors actor = new Actors();
                        double g1 = Double.parseDouble(c.getString("gps1"));
                        double g2 = Double.parseDouble(c.getString("gps2"));

                        myDistx = calculateDistance(act1, act2, g1, g2);

                        if (myDistx <= 50) {
                            actor.setLetter("x");
                            actor.setNazov(c.getString("nazov"));
                            actor.setThumb(c.getString("thumb"));
                            actor.setPerex(c.getString("perex"));
                            actor.setTyp(c.getString("typ"));
                            actor.setPlace(c.getString("place"));
                            actor.setGps1(c.getString("gps1"));
                            actor.setGps2(c.getString("gps2"));
                            actor.setExterier(c.getString("adresar"));

                            actor.setDist(myDistx);

                            actorsList.add(actor);
                            pocet++;
                        }
                    }

                    if (pocet == 0) {
                        runOnUiThread(new Runnable() {
                            public void run() {

                                Toast.makeText(Okoli.this.getApplicationContext(), R.string.nothing_around, Toast.LENGTH_LONG).show();
                            }
                        });

                    }

                    Collections.sort(actorsList, new Comparator<Actors>() {
                        @Override
                        public int compare(Actors lhs, Actors rhs) {
                            return lhs.getDist().compareTo(rhs.getDist());
                        }
                    });



                }  catch (final JSONException e) {
                    Okoli.this.runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            Toast.makeText(Okoli.this.getApplicationContext(),
                                    "Chyba dát: " + e.getMessage(),
                                    Toast.LENGTH_LONG).show();
                        }
                    }); }

                return true;

            } else {
                Okoli.this.runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        Toast.makeText(Okoli.this.getApplicationContext(),
                                "Chyba internetového pripojenia.",
                                Toast.LENGTH_LONG).show();
                    }
                });
                return false;
            }
        }

        final static double AVERAGE_RADIUS_OF_EARTH = 6371;
        double calculateDistance(double userLat, double userLng, double venueLat, double venueLng) {

            double latDistance = Math.toRadians(userLat - venueLat);
            double lngDistance = Math.toRadians(userLng - venueLng);

            double a = (Math.sin(latDistance / 2) * Math.sin(latDistance / 2)) +
                    (Math.cos(Math.toRadians(userLat))) *
                            (Math.cos(Math.toRadians(venueLat))) *
                            (Math.sin(lngDistance / 2)) *
                            (Math.sin(lngDistance / 2));

            double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));

            return (AVERAGE_RADIUS_OF_EARTH * c);
        }

        protected void onPostExecute(Boolean result) {
            super.onPostExecute(result);
            if (dialog != null && dialog.isShowing()) {
                dialog.dismiss();  dialog = null;
            }
            //dialog.dismiss();
            adapter.notifyDataSetChanged();
        }


    }


    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()){
            case android.R.id.home:
                onBackPressed();
                return true;
        }
        return super.onOptionsItemSelected(item);
    }

    @Override
    protected void onResume() { //restart activity after back from GPS settings
        super.onResume();
        adapter.clear();
        adapter.notifyDataSetChanged();

        if (dialog != null) {
            dialog.dismiss();
            dialog = null;
        }



        String action = getIntent().getAction();
        // Prevent endless loop by adding a unique action, don't restart if action is present
        if(action == null || !action.equals("created")) {


            String MY_PREFS_NAME = "resumecheck";
            SharedPreferences prefs = getSharedPreferences(MY_PREFS_NAME, MODE_PRIVATE);

                int idName = prefs.getInt("idName", 0); //0 is the default value.


            if(idName == 2) {
                Intent intent = new Intent(this, Okoli.class);
                startActivity(intent);
                finish();
            } else {
                SharedPreferences.Editor editor = getSharedPreferences(MY_PREFS_NAME, MODE_PRIVATE).edit();
                editor.putInt("idName", 1);
                editor.apply(); }



        }
        // Remove the unique action so the next time onResume is called it will restart
        else
            getIntent().setAction(null);


    }
}

然而,它运行良好,但控制台给我一个错误

android.view.WindowLeaked: Activity sk.hrady_zamky.darksymphony.hrady_zamkypremium.Okoli has leaked window DecorView@11bd862[] that was originally added here
                 at android.view.ViewRootImpl.<init>(ViewRootImpl.java:576)
                 at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:363)
                 at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:128)
                 at android.app.Dialog.show(Dialog.java:454)
                 at android.support.v7.app.AlertDialog$Builder.show(AlertDialog.java:1006)
                 at **sk.hrady_zamky.Okoli.showSettingsAlert(Okoli.java:298)
                 at sk.hrady_zamky.Okoli.onCreate(Okoli.java:95)**
                 at android.app.Activity.performCreate(Activity.java:7372)
                 at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1218)
                 at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3147)
                 at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3302)
                 at android.app.ActivityThread.-wrap12(Unknown Source:0)
                 at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1891)
                 at android.os.Handler.dispatchMessage(Handler.java:108)
                 at android.os.Looper.loop(Looper.java:166)
                 at android.app.ActivityThread.main(ActivityThread.java:7425)
                 at java.lang.reflect.Method.invoke(Native Method)
                 at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:245)
                 at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:921)

所以行95和298指向showsettingsalert。

我尝试取消Destroy、onPause、onpostExecute和onResume对话框,但错误仍然存在。当我按下设备GPS设置中的后退箭头,然后显示许可警报时,它显示的是准确的。

你能给我个建议,在什么地方以及如何取消那个警报窗口以避免泄漏吗?

共有1个答案

曹渝
2023-03-14

在取消对话框后,您应该使对话框在所有地方都为null

     if (dialog != null) 
     {
     dialog.dismiss();
     dialog = null;
     }

所以你的onDestroy应该是

@Override
public void onDestroy() {
super.onDestroy();
if (dialog != null) {
    dialog.dismiss();
    dialog = null;
}
}

像这样更改showSettingsAlert方法

public void showSettingsAlert() {
AlertDialog.Builder alertDialog = new AlertDialog.Builder(this);
alertDialog.setTitle("GPS is not Enabled!");
alertDialog.setMessage("Do you want to turn on GPS?");
alertDialog.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
    public void onClick(DialogInterface dialog, int which) {
        Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
        startActivity(intent);
    }
});

alertDialog.setNegativeButton("No", new DialogInterface.OnClickListener() {
    public void onClick(DialogInterface dialog, int which) {
        dialog.cancel();
    }
});

alertDialog.show();
}
 类似资料:
  • 圣灵所结的果子,就是仁爱、喜乐、和平、忍耐、恩慈、良善、信实、温柔、节制。这样的事,没有律法禁止。凡属基督耶稣的人,是已经把肉体连肉体的邪情私欲同钉在十字架上了。我们若是靠圣灵得生,就当靠圣灵行事。不要贪图虚名,彼此惹气,互相嫉妒。(GALATIANS 5:22-26) 生成器 上节中,我们曾经做过这样的操作: >>> my_tup = (x**x for x in range(4))>>> my

  • 1、为什么需要生成器 通过上面的学习,可以知道列表生成式,我们可以直接创建一个列表。 但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含 1000 万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。 所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢? 这样就不必创建完整的 li

  • 当你需要懒惰地生成一系列的值时,考虑使用一个“生成器函数” (generator function)。Dart 对这类生成器函数有内置的支持: 同步的生成器:返回一个 Iterable 对象。 异步的生成器:返回一个 Stream 对象。 要实现一个同步的生成器函数,使用 sync* 标记函数体,并使用 yield 语句传递值: Iterable<int> naturalsTo(int n) sy

  • 如果读过前一节,那你应该已经知道“迭代器”指的是一种可以被“for”循环使用的对象。换句话说,迭代器就是遵循迭代协议的对象。 而生成器则是迭代器的一种更为简洁的实现方法。这种写法不再需要构造一个类,而只需编写一个函数,函数每次运行到“yield”语句时都会返回一个值。下面的例子是用生成器来依次生成两个数之间的整数: def myrange(a, b): while a < b:

  • 通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。 所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间。在Python中,这种一边循

  • 通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。 所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间。在Python中,这种一边循