[英]OnResume / OnPause called multiple times
My MainActivity is loading different Fragments. 我的MainActivity正在加载不同的片段。 Furthermore, a Settings-Activity can be opened from the MainActivity.
此外,可以从MainActivity中打开Settings-Activity。
If the user is only switching between Fragments, everything is fine. 如果用户仅在片段之间切换,那么一切都很好。
When opening the Settings-Activity and going back to MainActivity, onResume and onPause gets called twice. 当打开Settings-Activity并返回MainActivity时,onResume和onPause会被调用两次。 If the user opens Settings-Activity and goes back again to MainActivity, onResume and onPause get called three times.
如果用户打开Settings-Activity并再次返回MainActivity,则会调用onResume和onPause 3次。 This increases each time the user opens Settings-Activity and going back to MainActivity.
每次用户打开Settings-Activity并返回MainActivity时,这种情况都会增加。
MainActivity 主要活动
public class MainActivity extends AppCompatActivity implements MyFragment.OnListFragmentInteractionListener, AsyncResponse {
private FragmentA fragmentA = new FragmentA();
private DatabaseHandler databaseHandler = new DatabaseHandler(this);
private NavigationView navigationView;
private DrawerLayout drawer;
private Toolbar toolbar;
// index to identify current nav menu item
private static int navItemIndex = 0;
public static String CURRENT_TAG = MyConstants.TAG_FRAGMENT_A;
// toolbar titles respected to selected nav menu item
private String[] activityTitles;
// flag to load home fragment when user presses back key
private Handler mHandler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
fragmentA.setDatabaseHandler(this.databaseHandler);
// Init UI
toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
mHandler = new Handler();
drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
navigationView = (NavigationView) findViewById(R.id.nav_view);
fabSendButton = (FloatingActionButton) findViewById(R.id.fab);
// Navigation view header
navHeader = navigationView.getHeaderView(0);
// load toolbar titles from string resources
activityTitles = getResources().getStringArray(R.array.sliding_menu_item_activity_titles);
// initializing navigation menu
setUpNavigationView();
if (savedInstanceState == null) {
navItemIndex = 0;
CURRENT_TAG = MyConstants.TAG_FRAGMENT_A;
loadHomeFragment();
}
}
/***
* Returns respected fragment that user
* selected from navigation menu
*/
private void loadHomeFragment() {
// set toolbar title
setToolbarTitle();
// if user select the current navigation menu again, don't do anything
// just close the navigation drawer
if (getSupportFragmentManager().findFragmentByTag(CURRENT_TAG) != null) {
drawer.closeDrawers();
return;
}
// Sometimes, when fragment has huge data, screen seems hanging
// when switching between navigation menus
// So using runnable, the fragment is loaded with cross fade effect
// This effect can be seen in GMail app
Runnable mPendingRunnable = new Runnable() {
@Override
public void run() {
// update the activity_main_header_with_item content by replacing fragments
Fragment fragment = getFragment();
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out);
fragmentTransaction.replace(R.id.frame, fragment, CURRENT_TAG);
fragmentTransaction.commit();
}
};
// If mPendingRunnable is not null, then add to the message queue
if (mPendingRunnable != null) {
mHandler.post(mPendingRunnable);
}
//Closing drawer on item click
drawer.closeDrawers();
// refresh toolbar menu
invalidateOptionsMenu();
}
private Fragment getFragment() {
switch (navItemIndex) {
case 0:
return this.fragmentA;
case 1:
Fragment B fragmentB = new FragmentB();
fragmentB.setDatabaseHandler(this.databaseHandler);
return fragmentB;
default:
return this.fragmentA;
}
}
private void setToolbarTitle() {
getSupportActionBar().setTitle(activityTitles[navItemIndex]);
}
private void setUpNavigationView() {
//Setting Navigation View Item Selected Listener to handle the item click of the navigation menu
navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
// This method will trigger on item Click of navigation menu
@Override
public boolean onNavigationItemSelected(MenuItem menuItem) {
//Check to see which item was being clicked and perform appropriate action
switch (menuItem.getItemId()) {
//Replacing the activity_main_header_with_item content with ContentFragment Which is our Inbox View;
case R.id.nav_A:
navItemIndex = 0;
CURRENT_TAG = MyConstants.TAG_FRAGMENT_A;
break;
case R.id.nav_B:
navItemIndex = 1;
CURRENT_TAG = MyConstants.TAG_FRAGMENT_B;
break;
default:
navItemIndex = 0;
}
loadHomeFragment();
return true;
}
});
ActionBarDrawerToggle actionBarDrawerToggle = new ActionBarDrawerToggle(this, drawer, toolbar, R.string.openDrawer, R.string.closeDrawer) {
@Override
public void onDrawerClosed(View drawerView) {
// Code here will be triggered once the drawer closes as we dont want anything to happen so we leave this blank
super.onDrawerClosed(drawerView);
}
@Override
public void onDrawerOpened(View drawerView) {
// Code here will be triggered once the drawer open as we dont want anything to happen so we leave this blank
super.onDrawerOpened(drawerView);
}
};
//Setting the actionbarToggle to drawer layout
drawer.setDrawerListener(actionBarDrawerToggle);
//calling sync state is necessary or else your hamburger icon wont show up
actionBarDrawerToggle.syncState();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main_header_with_item, menu);
return true;
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main_header_with_item, menu);
// Disable Player Icon in case no player is found on device
Intent intent = Intent.makeMainSelectorActivity(Intent.ACTION_MAIN, ScrobblOrDroidConstants.MUSIC_APP);
List<ResolveInfo> activities = getPackageManager().queryIntentActivities(intent, 0);
if(activities == null || activities.size() <= 0) {
MenuItem player = menu.findItem(R.id.player);
if(player != null){
player.setVisible(false);
}
}
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();
//noinspection SimplifiableIfStatement
if (id == R.id.player) {
Timber.i( "Added onClick listener to ImageView ivPlayer.");
Intent intent = Intent.makeMainSelectorActivity(Intent.ACTION_MAIN, ScrobblOrDroidConstants.MUSIC_APP);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
return true;
} else if (id == R.id.settings) {
// launch settings activity
startActivity(new Intent(MainActivity.this, SettingsActivity.class));
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
public void onResume() {
Timber.i("MainActivity.onResume-called.");
activityVisible = true;
updateHomeFragment();
callLongUserOperation();
super.onResume();
}
@Override
public void onPause() {
Timber.i("MainActivity.onPause-called.");
activityVisible = false;
super.onPause();
}
}
public void updateHomeFragment() {
if (CURRENT_TAG == MyConstants.TAG_HOME) {
Timber.i( "updating HomeFragment");
fragmentA.swap();
}
}
SettingsActivity 设置活动
public class SettingsActivity extends AppCompatPreferenceActivity implements SharedPreferences.OnSharedPreferenceChangeListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setupActionBar();
getFragmentManager().beginTransaction().replace(android.R.id.content, new MainPreferenceFragment()).commit();
}
private void setupActionBar() {
ViewGroup rootView = (ViewGroup)findViewById(R.id.action_bar_root);
View view = getLayoutInflater().inflate(R.layout.pref_toolbar, rootView, false);
rootView.addView(view, 0);
Toolbar toolbar = (Toolbar)findViewById(R.id.pref_toolbar);
setSupportActionBar(toolbar);
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
// Show the Up button in the action bar.
actionBar.setDisplayHomeAsUpEnabled(true);
}
}
public static class MainPreferenceFragment extends PreferenceFragment {
@Override
public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.pref_main);
// gallery EditText change listener
bindPreferenceSummaryToValue(findPreference(MyConstants.RECENTLY_SCROBBLED_KEY));
bindPreferenceSummaryToValue(findPreference(MyConstants.SCROBBLE_DURATION_KEY));
// feedback preference click listener
Preference myPref = findPreference("key_send_feedback");
myPref.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
public boolean onPreferenceClick(Preference preference) {
sendFeedback(getActivity());
return true;
}
});
// rating preference click listener
Preference myPrefRate = findPreference("key_send_rate");
myPrefRate.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
public boolean onPreferenceClick(Preference preference) {
sendRating(getActivity());
return true;
}
});
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) {
onBackPressed();
}
return super.onOptionsItemSelected(item);
}
private static void bindPreferenceSummaryToValue(Preference preference) {
preference.setOnPreferenceChangeListener(sBindPreferenceSummaryToValueListener);
sBindPreferenceSummaryToValueListener.onPreferenceChange(preference,
PreferenceManager.getDefaultSharedPreferences(preference.getContext()).getString(preference.getKey(), ""));
}
/**
* A preference value change listener that updates the preference's summary
* to reflect its new value.
*/
private static Preference.OnPreferenceChangeListener sBindPreferenceSummaryToValueListener = new Preference.OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
String stringValue = newValue.toString();
if(preference.getKey().equalsIgnoreCase(MyConstants.RECENTLY_SCROBBLED_KEY)){
preference.setSummary(stringValue + " " + preference.getContext().getResources().getString(R.string.pref_recently_scrobbled_summary));
}
if(preference.getKey().equalsIgnoreCase(MyConstants.SCROBBLE_DURATION_KEY)){
preference.setSummary(preference.getContext().getResources().getString(R.string.pref_scrobble_percentage_summary, stringValue));
}
return true;
}
};
/**
* Email client intent to send support mail
* Appends the necessary device information to email body
* useful when providing support
*/
public static void sendFeedback(Context context) {
String body = null;
try {
body = context.getPackageManager().getPackageInfo(context.getPackageName(), 0).versionName;
body = "\n\n-----------------------------\nPlease don't remove this information\n Device OS: Android \n Device OS version: " +
Build.VERSION.RELEASE + "\n App Version: " + body + "\n Device Brand: " + Build.BRAND +
"\n Device Model: " + Build.MODEL + "\n Device Manufacturer: " + Build.MANUFACTURER;
} catch (PackageManager.NameNotFoundException e) {
}
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("message/rfc822");
intent.putExtra(Intent.EXTRA_EMAIL, new String[]{MyConstants.E_MAIL_ADDRESS});
intent.putExtra(Intent.EXTRA_SUBJECT, "Feedback for " + context.getResources().getString(R.string.app_name));
intent.putExtra(Intent.EXTRA_TEXT, body);
context.startActivity(Intent.createChooser(intent, context.getString(R.string.pref_choose_email_client)));
}
public static void sendRating(Context context) {
Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse(MyConstants.PLAY_STORE_URL));
context.startActivity(i);;
}
@Override
public void onResume() {
super.onResume();
PreferenceManager.getDefaultSharedPreferences(getApplicationContext()).registerOnSharedPreferenceChangeListener(this);
}
@Override
public void onPause() {
PreferenceManager.getDefaultSharedPreferences(getApplicationContext()).registerOnSharedPreferenceChangeListener(this);
super.onPause();
}
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
if(key.equalsIgnoreCase(MyConstants.NOTIFICATION_ENABLED_KEY)){
EventBus.getDefault().post(new NotificationEvent());
Timber.i( "NotificationEvent Posted");
}
}
}
AppCompatPreferenceActivity AppCompatPreferenceActivity
public class AppCompatPreferenceActivity extends PreferenceActivity {
private AppCompatDelegate mDelegate;
@Override
protected void onCreate(Bundle savedInstanceState) {
getDelegate().installViewFactory();
getDelegate().onCreate(savedInstanceState);
super.onCreate(savedInstanceState);
}
@Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
getDelegate().onPostCreate(savedInstanceState);
}
public ActionBar getSupportActionBar() {
return getDelegate().getSupportActionBar();
}
public void setSupportActionBar(@Nullable Toolbar toolbar) {
getDelegate().setSupportActionBar(toolbar);
}
@Override
public MenuInflater getMenuInflater() {
return getDelegate().getMenuInflater();
}
@Override
public void setContentView(@LayoutRes int layoutResID) {
getDelegate().setContentView(layoutResID);
}
@Override
public void setContentView(View view) {
getDelegate().setContentView(view);
}
@Override
public void setContentView(View view, ViewGroup.LayoutParams params) {
getDelegate().setContentView(view, params);
}
@Override
public void addContentView(View view, ViewGroup.LayoutParams params) {
getDelegate().addContentView(view, params);
}
@Override
protected void onPostResume() {
super.onPostResume();
getDelegate().onPostResume();
}
@Override
protected void onTitleChanged(CharSequence title, int color) {
super.onTitleChanged(title, color);
getDelegate().setTitle(title);
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
getDelegate().onConfigurationChanged(newConfig);
}
@Override
protected void onStop() {
super.onStop();
getDelegate().onStop();
}
@Override
protected void onDestroy() {
super.onDestroy();
getDelegate().onDestroy();
}
public void invalidateOptionsMenu() {
getDelegate().invalidateOptionsMenu();
}
private AppCompatDelegate getDelegate() {
if (mDelegate == null) {
mDelegate = AppCompatDelegate.create(this, null);
}
return mDelegate;
}
}
AndroidManifest.xml AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.ordroid.My"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk
android:minSdkVersion="15"
android:targetSdkVersion="25" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme">
<activity
android:name=".ui.activity.MainActivity"
android:label="@string/app_name"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".ui.activity.LoginActivity"
android:excludeFromRecents="true"
android:label="@string/app_name"
android:screenOrientation="portrait"></activity>
<activity
android:name=".ui.activity.SettingsActivity"
android:label="@string/settings">
<!-- Parent activity meta-data to support 4.0 and lower -->
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".ui.activity.MainActivity" />
</activity>
<!-- start service on device boot complete -->
<receiver
android:name=".util.receiver.MyBroadcastReceiver"
android:enabled="true"
android:exported="true"
android:label="StartMyServiceAtBootReceiver">
<intent-filter>
<action android:name="com.android.music.metachanged" />
<action android:name="com.android.music.playstatechanged" />
<!-- <action android:name="android.intent.action._BOOT_COMPLETED" /> -->
</intent-filter>
</receiver>
<receiver android:name=".util.receiver.MyInternetConnectionBroadcastReceiver">
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
</intent-filter>
</receiver>
</application>
</manifest>
How can I avoid these multiple calls? 如何避免这些多次通话?
Seems it was a bug in the Android SDK Build Tool. 似乎是Android SDK构建工具中的错误。 After updating it works as a charme!
更新后,它可以作为一个魅力!
I faced the same issue where onResume() of one of my Activities was getting called thrice. 我遇到一个相同的问题,其中我的一个活动的onResume()被称为三次。
I fixed it by seting a boolean in onCreate() of the corresponding activity as false. 我通过将相应活动的onCreate()中的布尔值设置为false来解决此问题。 For example:
例如:
boolean onResumeCalled = false
and every time the activity is created, I keep onResumeCalled as false. 并且每次创建活动时,我都会将onResumeCalled保留为false。
In onResume(), I set a check 在onResume()中,我设置了一个检查
if(!onResumeCalled)
in the start of onResume(). 在onResume()的开头。
Now, when the activity is created, onResumeCalled is false. 现在,当创建活动时,onResumeCalled为false。 Then, once the methods inside onResume() are called, I change the value of onResumeCalled to true, so that the second time when onResume() is called, the methods inside onResume() will not be accessed because the value of onResumeCalled is now true.
然后,一旦调用了onResume()内部的方法,我便将onResumeCalled的值更改为true,以便第二次调用onResume()时将不再访问onResume()内部的方法,因为现在onResumeCalled的值真正。
I found here some reason of that behaviour on Android. 我在这里找到了在Android上发生这种行为的一些原因。 For me this was the reason.
对我来说,这就是原因。
onPause-onResume-onPause-onResume just happens every time, when app is starting first time after installation.
在安装后首次启动应用程序时,onPause-onResume-onPause-onResume只会在每次发生。 You can simply invoke this behavior by doing any change in code and rerunning (which includes recompiling) the app from your IDE.
您可以通过在代码中进行任何更改并从IDE重新运行(包括重新编译)应用程序来简单地调用此行为。
No matter if you use AppCompat libs or not.
无论您是否使用AppCompat库。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.