“活动已泄露最初添加的窗口”

时间:2017-01-18 10:56:56

标签: java android eclipse sqlite

我有以下代码,我想将Mysql与SQLITE同步。问题是当我点击同步按钮时出现错误。数据正在从Mysql服务器传输到我的SQLITE,但它不会出现在我将数据放入列表的应用程序的活动中。

public class MainActivity extends ActionBarActivity {
    // DB Class to perform DB related operations
    DBController controller = new DBController(this);
    // Progress Dialog Object
    ProgressDialog prgDialog;
    HashMap<String, String> queryValues;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // Get User records from SQLite DB
        ArrayList<HashMap<String, String>> userList = controller.getAllUsers();
        // If users exists in SQLite DB
        if (userList.size() != 0) {
            // Set the User Array list in ListView
            ListAdapter adapter = new SimpleAdapter(MainActivity.this, userList, R.layout.view_user_entry, new String[] {
                            "userId", "userName" }, new int[] { R.id.userId, R.id.userName });
            ListView myList = (ListView) findViewById(android.R.id.list);
            myList.setAdapter(adapter);
        }
        // Initialize Progress Dialog properties
        prgDialog = new ProgressDialog(this);
        prgDialog.setMessage("Transferring Data from Remote MySQL DB and Syncing SQLite. Please wait...");
        prgDialog.setCancelable(false);
        // BroadCase Receiver Intent Object
        Intent alarmIntent = new Intent(getApplicationContext(), SampleBC.class);
        // Pending Intent Object
        PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT);
        // Alarm Manager Object
        AlarmManager alarmManager = (AlarmManager) getApplicationContext().getSystemService(Context.ALARM_SERVICE);
        // Alarm Manager calls BroadCast for every Ten seconds (10 * 1000), BroadCase further calls service to check if new records are inserted in 
        // Remote MySQL DB
        alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, Calendar.getInstance().getTimeInMillis() + 5000, 10 * 1000, pendingIntent);
    }

    // Options Menu (ActionBar Menu)
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    // When Options Menu is selected
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. 
        int id = item.getItemId();
        // When Sync action button is clicked
        if (id == R.id.refresh) {
            // Transfer data from remote MySQL DB to SQLite on Android and perform Sync
            syncSQLiteMySQLDB();
            return true;
        }
        return super.onOptionsItemSelected(item);
    }

    // Method to Sync MySQL to SQLite DB
    public void syncSQLiteMySQLDB() {
        // Create AsycHttpClient object
        AsyncHttpClient client = new AsyncHttpClient();
        // Http Request Params Object
        RequestParams params = new RequestParams();
        // Show ProgressBar
        prgDialog.show();

        // Make Http call to getusers.php
        client.post("http://download.grupsapte.ro/sinc/getusers.php", params, new AsyncHttpResponseHandler() {
                @Override
                public void onSuccess(String response) {
                    // Hide ProgressBar
                    prgDialog.hide();
                    // Update SQLite DB with response sent by getusers.php
                    updateSQLite(response);
                }
                // When error occured
                @Override
                public void onFailure(int statusCode, Throwable error, String content) {
                    // TODO Auto-generated method stub
                    // Hide ProgressBar
                    prgDialog.hide();
                    if (statusCode == 404) {
                        Toast.makeText(getApplicationContext(), "Requested resource not found", Toast.LENGTH_LONG).show();
                    } else if (statusCode == 500) {
                        Toast.makeText(getApplicationContext(), "Something went wrong at server end", Toast.LENGTH_LONG).show();
                    } else {
                        Toast.makeText(getApplicationContext(), "Unexpected Error occcured! [Most common Error: Device might not be connected to Internet]",
                                Toast.LENGTH_LONG).show();
                    }
                }
        });
    }

    public void updateSQLite(String response){
        ArrayList<HashMap<String, String>> usersynclist;
        usersynclist = new ArrayList<HashMap<String, String>>();
        // Create GSON object
        Gson gson = new GsonBuilder().create();
        try {
            // Extract JSON array from the response
            JSONArray arr = new JSONArray(response);
            System.out.println(arr.length());
            // If no of array elements is not zero
            if(arr.length() != 0){
                // Loop through each array element, get JSON object which has userid and username
                for (int i = 0; i < arr.length(); i++) {
                    // Get JSON object
                    JSONObject obj = (JSONObject) arr.get(i);
                    System.out.println(obj.get("userId"));
                    System.out.println(obj.get("userName"));
                    // DB QueryValues Object to insert into SQLite
                    queryValues = new HashMap<String, String>();
                    // Add userID extracted from Object
                    queryValues.put("userId", obj.get("userId").toString());
                    // Add userName extracted from Object
                    queryValues.put("userName", obj.get("userName").toString());
                    // Insert User into SQLite DB
                    controller.insertUser(queryValues);
                    HashMap<String, String> map = new HashMap<String, String>();
                    // Add status for each User in Hashmap
                    map.put("Id", obj.get("userId").toString());
                    map.put("status", "1");
                    usersynclist.add(map);
                }
                // Inform Remote MySQL DB about the completion of Sync activity by passing Sync status of Users
                updateMySQLSyncSts(gson.toJson(usersynclist));
                // Reload the Main Activity
                reloadActivity();
            }
        } catch (JSONException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    // Method to inform remote MySQL DB about completion of Sync activity
    public void updateMySQLSyncSts(String json) {
        System.out.println(json);
        AsyncHttpClient client = new AsyncHttpClient();
        RequestParams params = new RequestParams();
        params.put("syncsts", json);
        // Make Http call to updatesyncsts.php with JSON parameter which has Sync statuses of Users
        client.post("http://download.grupsapte.ro/sinc/updatesyncsts.php", params, new AsyncHttpResponseHandler() {
            @Override
            public void onSuccess(String response) {
                Toast.makeText(getApplicationContext(), "MySQL DB has been informed about Sync activity", Toast.LENGTH_LONG).show();
            }

            @Override
            public void onFailure(int statusCode, Throwable error, String content) {
                    Toast.makeText(getApplicationContext(), "Error Occured", Toast.LENGTH_LONG).show();
            }
        });
    }

    // Reload MainActivity
    public void reloadActivity() {
        Intent objIntent = new Intent(getApplicationContext(), MainActivity.class);
        startActivity(objIntent);
    }
}

错误如下:

01-18 12:54:59.821: E/WindowManager(2022): android.view.WindowLeaked: Activity com.prgguru.example.MainActivity has leaked window com.android.internal.policy.PhoneWindow$DecorView{a19b187 G.E...... R.....ID 0,0-1336,384} that was originally added here
01-18 12:54:59.821: E/WindowManager(2022):  at android.view.ViewRootImpl.<init>(ViewRootImpl.java:565)
01-18 12:54:59.821: E/WindowManager(2022):  at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:326)
01-18 12:54:59.821: E/WindowManager(2022):  at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:91)
01-18 12:54:59.821: E/WindowManager(2022):  at android.app.Dialog.show(Dialog.java:350)
01-18 12:54:59.821: E/WindowManager(2022):  at com.prgguru.example.MainActivity.syncSQLiteMySQLDB(MainActivity.java:96)
01-18 12:54:59.821: E/WindowManager(2022):  at com.prgguru.example.MainActivity.onOptionsItemSelected(MainActivity.java:83)
01-18 12:54:59.821: E/WindowManager(2022):  at android.app.Activity.onMenuItemSelected(Activity.java:3204)
01-18 12:54:59.821: E/WindowManager(2022):  at android.support.v4.app.FragmentActivity.onMenuItemSelected(FragmentActivity.java:353)
01-18 12:54:59.821: E/WindowManager(2022):  at android.support.v7.app.ActionBarActivity.superOnMenuItemSelected(ActionBarActivity.java:244)
01-18 12:54:59.821: E/WindowManager(2022):  at android.support.v7.app.ActionBarActivityDelegateICS.onMenuItemSelected(ActionBarActivityDelegateICS.java:165)
01-18 12:54:59.821: E/WindowManager(2022):  at android.support.v7.app.ActionBarActivity.onMenuItemSelected(ActionBarActivity.java:130)
01-18 12:54:59.821: E/WindowManager(2022):  at android.support.v7.app.ActionBarActivityDelegateICS$WindowCallbackWrapper.onMenuItemSelected(ActionBarActivityDelegateICS.java:300)
01-18 12:54:59.821: E/WindowManager(2022):  at com.android.internal.policy.PhoneWindow.onMenuItemSelected(PhoneWindow.java:1259)
01-18 12:54:59.821: E/WindowManager(2022):  at com.android.internal.view.menu.MenuBuilder.dispatchMenuItemSelected(MenuBuilder.java:801)
01-18 12:54:59.821: E/WindowManager(2022):  at com.android.internal.view.menu.MenuItemImpl.invoke(MenuItemImpl.java:155)
01-18 12:54:59.821: E/WindowManager(2022):  at com.android.internal.view.menu.MenuBuilder.performItemAction(MenuBuilder.java:954)
01-18 12:54:59.821: E/WindowManager(2022):  at com.android.internal.view.menu.MenuBuilder.performItemAction(MenuBuilder.java:944)
01-18 12:54:59.821: E/WindowManager(2022):  at android.widget.ActionMenuView.invokeItem(ActionMenuView.java:655)
01-18 12:54:59.821: E/WindowManager(2022):  at com.android.internal.view.menu.ActionMenuItemView.onClick(ActionMenuItemView.java:251)
01-18 12:54:59.821: E/WindowManager(2022):  at android.view.View.performClick(View.java:5697)
01-18 12:54:59.821: E/WindowManager(2022):  at android.widget.TextView.performClick(TextView.java:10826)
01-18 12:54:59.821: E/WindowManager(2022):  at android.view.View$PerformClick.run(View.java:22526)
01-18 12:54:59.821: E/WindowManager(2022):  at android.os.Handler.handleCallback(Handler.java:739)
01-18 12:54:59.821: E/WindowManager(2022):  at android.os.Handler.dispatchMessage(Handler.java:95)
01-18 12:54:59.821: E/WindowManager(2022):  at android.os.Looper.loop(Looper.java:158)
01-18 12:54:59.821: E/WindowManager(2022):  at android.app.ActivityThread.main(ActivityThread.java:7225)
01-18 12:54:59.821: E/WindowManager(2022):  at java.lang.reflect.Method.invoke(Native Method)
01-18 12:54:59.821: E/WindowManager(2022):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
01-18 12:54:59.821: E/WindowManager(2022):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)

我知道我应该放一个this.finish(),但我不确切知道在哪里。希望有人帮助我。

5 个答案:

答案 0 :(得分:1)

public void syncSQLiteMySQLDB() {
   // Create AsycHttpClient object
   AsyncHttpClient client = new AsyncHttpClient();
   // Http Request Params Object
   RequestParams params = new RequestParams();
   // Show ProgressBar
   prgDialog = new ProgressDialog(MainActivity.this);
   prgDialog.setMessage("Transferring Data from Remote MySQL DB and Syncing SQLite. Please wait...");
   prgDialog.setCancelable(false);
   prgDialog.show();

   // Make Http call to getusers.php
   client.post("http://download.grupsapte.ro/sinc/getusers.php", params, new AsyncHttpResponseHandler() {
           @Override
           public void onSuccess(String response) {

               // Update SQLite DB with response sent by getusers.php
               updateSQLite(response);
           }
           // When error occured
           @Override
           public void onFailure(int statusCode, Throwable error, String content) {
               // TODO Auto-generated method stub

               if (statusCode == 404) {
                   Toast.makeText(getApplicationContext(), "Requested resource not found", Toast.LENGTH_LONG).show();
               } else if (statusCode == 500) {
                   Toast.makeText(getApplicationContext(), "Something went wrong at server end", Toast.LENGTH_LONG).show();
               } else {
                   Toast.makeText(getApplicationContext(), "Unexpected Error occcured! [Most common Error: Device might not be connected to Internet]",
                           Toast.LENGTH_LONG).show();
               }
           }

            @Override
            public void onFinish(){
                // Hide ProgressBar
                if(prgDialog.isShowing())
               prgDialog.hide();
            }
   });

}

首先,您应该声明本地进度条对象并使用MainActivity初始化。这也是AsyncHttpClient有一个方法onFinish(),它将在调用成功或失败后调用,因此您只需要在onfinsh方法中隐藏进度条,你总是应该检查进度条是否显示,这样就不会导致产生异常

答案 1 :(得分:0)

尝试,   在显示进度对话框之前。检查它是否已经显示,如果是,则将其关闭并显示对话框。

在syncSQLiteMySQLDB中,您将显示进度对话框。首先检查您是否已经有一个prgDialog实例及其显示。然后关闭现有的prgDialog并显示。并在显示之前检查活动是否未完成

public void syncSQLiteMySQLDB() {
....
if( !isFinishing()) {
    if(prgDialog !=null) {
        if(prgDialog.isShowing()) {
              prgDialog.dismiss()
        }
        prgDialog.show();
    }

  }
}

答案 2 :(得分:0)

您需要dismiss()progressDialog

@Override
            public void onSuccess(String response) {
                // dismiss ProgressBar
                if (prgDialog != null) {
                prgDialog.dismiss(); //not hide try dismiss the dialog
                // Update SQLite DB with response sent by getusers.php
                updateSQLite(response);
            }
        }

也在您的onFailure方法dismiss()dialog

答案 3 :(得分:0)

您正在重新加载活动而不关闭对话框,所以您应该首先解雇。

public void reloadActivity() {
           // dissmiss dialog first then reload activity.
            if(prgDialog.isShowing()) {
              prgDialog.dismiss();
              Intent objIntent = new Intent(getApplicationContext(), MainActivity.class);
              startActivity(objIntent);
             }

    }

答案 4 :(得分:0)

花了几分钟找到此内存泄漏,无需在准备对话框生成器中使用.show

  @Override
  protected void onPrepareDialogBuilder(final AlertDialog.Builder builder) {

        builder
           .setIcon(getIconImage(context))
           .setTitle("title)
           .setMessage("message")
           .setPositiveButton("ok",
                  new DialogInterface.OnClickListener() {
                      public void onClick(DialogInterface dialog, int which) {
                         dialog.cancel();
                          start intent
                      }
                  })
           .setNegativeButton("cancel",
                  new DialogInterface.OnClickListener() {
                      public void onClick(DialogInterface dialog, int which) {
                         dialog.cancel();

                     }
                  })
            .show();

  }
  else{
         do something else
   }
}