当我在我的应用程序中旋转手机后,当我点击手机上的菜单键/按钮(设备上主页按钮左侧的按钮)以显示小设置对话框时,会发生这种情况。
我已经对这个问题进行了很多搜索,我知道我的活动被销毁时需要关闭/关闭此对话框(onDestroy()
)。问题是我不知道如何才能做到这一点。
更奇怪的是,如果我点击我的应用程序操作栏上的设置按钮来显示小设置对话框,我在设备中旋转设备没有异常。只有在我使用设备的菜单按钮时才会出现例外情况。
这是我正在谈论的菜单键/按钮:
点击菜单键后弹出小设置对话框,这是我的应用程序,如果我旋转设备,则生成异常:
以下是在从上一张图像旋转设备后生成异常AKA后的设备:
我正在运行android 4.4.2 CyanogenMod。
以下是我认为可能与此问题相关的代码:
@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;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_menu_settings)
{
SettingsFragment settingsFragment = new SettingsFragment();
// settingsFragment.setHttpService(appService);
getFragmentManager().beginTransaction().replace(R.id.content_frame, settingsFragment).addToBackStack("Settings").commit();
return true;
}
else if(mDrawerToggle.onOptionsItemSelected(item)) {
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
// If the drawer is open, hide action items related to the content view
Log.d(TAG, "Butao do menu");
boolean drawerOpen = mDrawerLayout.isDrawerOpen(mDrawerList);
menu.findItem(R.id.action_menu_settings).setVisible(!drawerOpen);
return super.onPrepareOptionsMenu(menu);
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// Pass any configuration change to the drawer toggles
mDrawerToggle.onConfigurationChanged(newConfig);
Log.d(TAG, "onConfigurationChanged - Activity");
}
我尝试在closeOptionsMenu()
上调用onDestroy()
方法,但没有成功。
@Override
protected void onDestroy() {
super.onDestroy();
closeOptionsMenu();
}
这是这个堆栈跟踪:
android.view.WindowLeaked: Activity com.my.package.design.MainActivity has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView{41865120 V.E..... ......I. 0,0-399,84} that was originally added here
at android.view.ViewRootImpl.<init>(ViewRootImpl.java:348)
at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:248)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:69)
at com.android.internal.policy.impl.PhoneWindow.openPanel(PhoneWindow.java:725)
at com.android.internal.policy.impl.PhoneWindow.openPanelsAfterRestore(PhoneWindow.java:1899)
at com.android.internal.policy.impl.PhoneWindow.access$2200(PhoneWindow.java:128)
at com.android.internal.policy.impl.PhoneWindow$DecorView.onAttachedToWindow(PhoneWindow.java:2939)
at android.view.View.dispatchAttachedToWindow(View.java:12592)
at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:2458)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1217)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1000)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5670)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:761)
at android.view.Choreographer.doCallbacks(Choreographer.java:574)
at android.view.Choreographer.doFrame(Choreographer.java:544)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:747)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5081)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:791)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:607)
at dalvik.system.NativeStart.main(Native Method)
非常感谢任何帮助。
------------------编辑------------------------- - 这是我的完整MainActivity.class代码
public class MainActivity extends Activity {
private String hello = "hello";
private static final String TAG = "MainActivity";
private static final String TAG_TASK_FRAGMENT = "task_fragment";
// private final MainLooperSpy mainLooperSpy = new MainLooperSpy();
private boolean isBound = false;
private RetainedFragment retainedFragment;
private WebService webService;
// Get application context
final Context appContext = ApplicationContextProvider.getContext();
// Menu item tittle
private static final String MENU_TITTLE = "Select an Item";
// Within which the entire activity is enclosed
private DrawerLayout mDrawerLayout;
// ListView represents Navigation Drawer
private ListView mDrawerList;
// ActionBarDrawerToggle indicates the presence of Navigation Drawer in the action bar
private ActionBarDrawerToggle mDrawerToggle;
private CharSequence mDrawerTitle;
private CustomDrawerAdapter adapter;
List<DrawerItem> dataList;
// Title of the action bar
String mTitle="";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
webService = ApplicationContextProvider.getWebService();
dataList = new ArrayList<DrawerItem>();
mDrawerTitle = getTitle();
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
mDrawerList = (ListView) findViewById(R.id.drawer_list);
mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START);
dataList.add(new DrawerItem(true)); // adding a spinner to the list
dataList.add(new DrawerItem("Contacts")); // adding a header to the list
dataList.add(new DrawerItem("Contact List", R.drawable.ic_action_email));
dataList.add(new DrawerItem("Duplicates", R.drawable.ic_action_good));
dataList.add(new DrawerItem("Similares", R.drawable.ic_action_gamepad));
dataList.add(new DrawerItem("Http Server"));// adding a header to the list
dataList.add(new DrawerItem("Configuration", R.drawable.ic_action_search));
dataList.add(new DrawerItem("Backups")); // adding a header to the list
dataList.add(new DrawerItem("Local Backups", R.drawable.ic_action_import_export));
dataList.add(new DrawerItem("Cloud Backups", R.drawable.ic_action_cloud));
dataList.add(new DrawerItem("Help", R.drawable.ic_action_help));
adapter = new CustomDrawerAdapter(this, R.layout.custom_drawer_item, dataList);
mDrawerList.setAdapter(adapter);
mTitle = getTitle().toString();
mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, R.drawable.ic_drawer, R.string.drawer_open, R.string.drawer_close){
// Called when drawer is closed
public void onDrawerClosed(View view)
{
super.onDrawerClosed(view);
getActionBar().setTitle(mTitle);
}
// Called when a drawer is opened
public void onDrawerOpened(View drawerView)
{
super.onDrawerOpened(drawerView);
getActionBar().setTitle(MENU_TITTLE);
}
};
// Setting DrawerToggle on DrawerLayout
mDrawerLayout.setDrawerListener(mDrawerToggle);
// Creating an ArrayAdapter to add items to the listview mDrawerList
ArrayAdapter<String> adapter = new ArrayAdapter<String>(getBaseContext(), R.layout.drawer_list_item, getResources().getStringArray(R.array.menu_list));
// Setting item click listener for the listview mDrawerList
mDrawerList.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if (dataList.get(position).getTitle() == null)
{
selectItem(position);
}
}
});
// Set the App icon has up button
ActionBar actionBar = getActionBar();
actionBar.setHomeButtonEnabled(true);
actionBar.setDisplayHomeAsUpEnabled(true);
actionBar.setDisplayShowHomeEnabled(true);
if (savedInstanceState == null)
{
if (dataList.get(0).isSpinner() & dataList.get(1).getTitle() != null)
{
selectItem(3); // 2
}
else if (dataList.get(0).getTitle() != null)
{
selectItem(1);
}
else
{
selectItem(0);
}
}
PreferenceManager.setDefaultValues(this, R.xml.preferences, false);
FragmentManager fm = getFragmentManager();
retainedFragment = (RetainedFragment) fm.findFragmentByTag(TAG_TASK_FRAGMENT);
if (retainedFragment == null)
{
retainedFragment = new RetainedFragment();
fm.beginTransaction().add(retainedFragment, TAG_TASK_FRAGMENT).commit();
}
} // end onCreate()
@Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
// Sync the toggle state after onRestoreInstanceState has occurred.
mDrawerToggle.syncState();
}
@Override
public void setTitle(CharSequence title) {
getActionBar().setTitle(title);
}
@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;
}
/** Handling the touch event of app icon and settings icon */
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_menu_settings)
{
SettingsFragment settingsFragment = new SettingsFragment();
// settingsFragment.setHttpService(appService);
getFragmentManager().beginTransaction().replace(R.id.content_frame, settingsFragment).addToBackStack("Settings").commit();
return true;
}
else if(mDrawerToggle.onOptionsItemSelected(item)) {
return true;
}
return super.onOptionsItemSelected(item);
}
/** Called whenever we call invalidateOptionsMenu() */
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
// If the drawer is open, hide action items related to the content view
Log.d(TAG, "Butao do menu");
boolean drawerOpen = mDrawerLayout.isDrawerOpen(mDrawerList);
menu.findItem(R.id.action_menu_settings).setVisible(!drawerOpen);
return super.onPrepareOptionsMenu(menu);
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// Pass any configuration change to the drawer toggles
mDrawerToggle.onConfigurationChanged(newConfig);
Log.d(TAG, "onConfigurationChanged - Activity");
}
public void selectItem(int position) {
Fragment fragment = null;
switch (position) {
case 2:
fragment = new PlaceholderFragment();
break;
case 3:
fragment = new ContactMenuFragment();
break;
case 4:
fragment = new ContactMenuFragment();
break;
case 6:
fragment = new HttpMenuFragment();
break;
case 8:
fragment = new SlidingFragment();
break;
case 9:
fragment = new SlidingFragment();
break;
case 10:
fragment = new SlidingFragment();
break;
default:
break;
}
FragmentManager frgManager = getFragmentManager();
frgManager.beginTransaction().replace(R.id.content_frame, fragment).commit();
mDrawerList.setItemChecked(position, true);
setTitle(dataList.get(position).getItemName());
mDrawerLayout.closeDrawer(mDrawerList);
}
// Bind to the service
@Override
protected void onStart()
{
super.onStart();
if(webService.isStarted() == false)
{
webService.startServer(appContext);
}
}
@Override
protected void onStop()
{
super.onStop();
if(webService.isStarted() == true)
{
webService.stopServer();
}
Log.d(TAG, "onStop - Activity");
// mainLooperSpy.dumpQueue();
}
// Check whether the http server is set to run at startup or not
// From the preferences settings
public boolean isServerSetToRunAtStartUp()
{
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
if(sharedPreferences.contains(SettingsFragment.HTTP_RUN_AT_STARTUP))
{
Log.d(TAG, "Key found!");
}
else
{
Log.d(TAG, "Key does not exist!");
}
if(sharedPreferences.getBoolean(SettingsFragment.HTTP_RUN_AT_STARTUP, false) == false)
{
return false;
}
if(sharedPreferences.getBoolean(SettingsFragment.HTTP_RUN_AT_STARTUP, false) == true)
{
Log.d(TAG, "isServerSetToRunAtStartUp - deu verdadeiro");
return true;
}
return false;
}
@Override
protected void onUserLeaveHint() {
super.onUserLeaveHint();
Log.d(TAG, "onUserLeaveHint - Activity");
// mainLooperSpy.dumpQueue();
}
@Override
public void onUserInteraction() {
super.onUserInteraction();
Log.d(TAG, "onUserInteraction - Activity");
// mainLooperSpy.dumpQueue();
}
@Override
protected void onPause() {
super.onPause();
Log.d(TAG, "onPause - Activity");
// mainLooperSpy.dumpQueue();
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
closeOptionsMenu();
Log.d(TAG, "onSaveInstanceState - Activity");
// mainLooperSpy.dumpQueue();
}
@Override
protected void onResume() {
super.onResume();
Log.d(TAG, "onResume - Activity");
// mainLooperSpy.dumpQueue();
}
@Override
protected void onDestroy() {
closeOptionsMenu();
super.onDestroy();
// closeOptionsMenu();
Log.d(TAG, "onDestroy - Activity");
webService.stopServer();
// mainLooperSpy.dumpQueue();
}
}
答案 0 :(得分:0)
如果查看堆栈跟踪,它会指出窗口泄漏发生在PhoneWindow类的第725行。发生错误的原因是您尝试将新视图添加到已更改或已被删除或尚未初始化的窗口。在添加视图或更改该布局中的视图之前,请确保您的布局已建立且稳定。