我有一个主要 Activity ,其中一个监听器放在 onCreate Hook 中的 MutableLiveData 集上:
userService.getPfcRepository().getUserLogged().observe(this, user -> {
if (user != null) {
setUserPets(user);
setUserDataInNavBar(user);
}
});
启动登录 Activity 后,该值会发生更改。在此 Activity 中放入 MutableLiveData
的另一个监听器正在按预期工作,但是当登录 Activity 完成并且主 Activity 返回前台时,我注意到监听器尚未被触发(通过验证)日志)。
这个问题的根源可能是什么?
主要 Activity
public class MainActivity extends AppCompatActivity implements
PetFragment.OnListFragmentInteractionListener,
AccountManagementFormFragment.OnSaveButtonClickListener{
private static final int LOGIN_REQUEST = 1;
private static final int ADD_PET_REQUEST = 2;
/** LOGGING */
private static final String TAG = "MainActivity";
@Inject
UserService userService;
@Inject
PhotoService photoService;
...
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
((PetFoodingControl) getApplicationContext()).getServicesComponent().inject(this);
setContentView(R.layout.activity_main);
toolbar = findViewById(R.id.main_toolbar);
setSupportActionBar(toolbar);
setupAddButton();
DrawerLayout drawer = findViewById(R.id.drawer_layout);
NavigationView navigationView = findViewById(R.id.nav_view);
// Passing each menu ID as a set of Ids because each
// menu should be considered as top level destinations.
mAppBarConfiguration = new AppBarConfiguration.Builder(
R.id.nav_pets, R.id.nav_account_settings)
.setDrawerLayout(drawer)
.build();
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
NavigationUI.setupActionBarWithNavController(this, navController, mAppBarConfiguration);
NavigationUI.setupWithNavController(navigationView, navController);
headerView = navigationView.getHeaderView(0);
getUserDataView();
setupLogoutListener();
setupUserLoggedListener();
if (userService.getPfcRepository().getUserLogged().getValue() == null) {
launchLoginActivity();
}
}
/**
* Setup userLoggedListener
*/
private void setupUserLoggedListener() {
userService.getPfcRepository().getUserLogged().observe(this, user -> {
if (user != null) {
setUserPets(user);
setUserDataInNavBar(user);
}
});
}
...
/**
* Launch login activity trough explicit intent.
*/
public void launchLoginActivity() {
Intent loginActivityIntent = new Intent(this, LoginActivity.class);
startActivityForResult(loginActivityIntent, LOGIN_REQUEST);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == LOGIN_REQUEST && resultCode != RESULT_OK) {
finishAndRemoveTask();
}
}
...
@Override
protected void onDestroy() {
userService.clearDisposables(this);
photoService.clearDisposables(this);
userService.leave();
super.onDestroy();
}
登录 Activity
@Inject
UserService userService;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
((PetFoodingControl) getApplicationContext()).getServicesComponent().inject(this);
setContentView(R.layout.activity_login);
if (savedInstanceState == null) {
setupUserLoggedListener();
}
userService.initLogin(this);
}
...
/**
* Action invoked when login button is clicked
* @param email entered
* @param password entered
*/
public void onLoginButtonClick(String email, String password) {
if (email.isEmpty() || password.isEmpty()) {
showToast(R.string.toast_input_empty);
} else {
tryToLog(email, password,
((CheckBox) findViewById(R.id.chk_keep_logged_in)).isChecked());
}
}
...
/**
* Try to log with the data provided (email, password and keep logged).
* @param email the email entered
* @param password the password entered
* @param isKeepLogged true if "keep logged" checked, false otherwise
*/
private void tryToLog(String email, String password, boolean isKeepLogged) {
userService.tryToLog(this, email, password, isKeepLogged).observe(this,
result -> {
if (result == 1) {
showToast(R.string.toast_failed_login);
} else if (result == 0) {
showToast(R.string.toast_success_login);
}
});
}
/**
* Setup a listener to load the login fields if no user is logged or the welcome fragment
* in the contrary.
*/
private void setupUserLoggedListener() {
userService.getPfcRepository().getUserLogged().observe(this, user -> {
if (user == null) {
loadFragment(LoginFieldsFragment.newInstance());
} else {
loadFragment(LoginWelcomeFragment.newInstance());
}
});
}
/**
* Return to the Main activity, and finishes the Login activity.
*/
public void finishLoginActivity(int resultCode) {
Intent retIntent = new Intent();
setResult(resultCode, retIntent);
finish();
}
@Override
protected void onDestroy() {
userService.clearDisposables(this);
super.onDestroy();
}
用户服务Impl
public class UserServiceImpl extends PetFoodingControlService implements UserService {
/** LOGGING */
private static final String TAG = "UserService";
/** PREFERENCES AUTO LOGIN KEY */
private static final String AUTO_LOGIN_TOKEN = "autoLoginToken";
/** Disposable management */
private Map<Context, CompositeDisposable> compositeDisposableMap = new HashMap<>();
private PetFoodingControlRepository pfcRepository;
private SharedPreferences sharedPreferences;
@Inject
public UserServiceImpl(PetFoodingControlRepository pfcRepository,
SharedPreferences sharedPreferences) {
this.pfcRepository = pfcRepository;
this.sharedPreferences = sharedPreferences;
}
/**
* Init the login process.
* @param context the Context of the caller
*/
@Override
public void initLogin(Context context) {
String autoLogin = sharedPreferences.getString(AUTO_LOGIN_TOKEN,"");
if (!autoLogin.isEmpty()) {
Log.i(TAG, "Auto login value stored in preferences : " + autoLogin);
tryToAutologin(context, autoLogin);
} else {
pfcRepository.setUserLogged(null);
}
}
/**
* Try to log with auto login with the local token given as a parameter.
* @param autoLoginLocalToken the local auto login token
*/
private void tryToAutologin(Context context, String autoLoginLocalToken) {
Disposable disposable = pfcRepository.getUserByAutoLogin(autoLoginLocalToken).subscribe(
user -> {
Log.i(TAG, "User from AutoLogin successfully retrieved");
pfcRepository.setUserLogged(user);
}, throwable -> {
Log.e(TAG, "AutoLogin failed", throwable);
pfcRepository.setUserLogged(null);
});
addToCompositeDisposable(context, disposable);
}
/**
* Try to log in with the data provided, initiate the auto login feature saving and storing
* in preferences if necessary.
* Return a SingleLiveEvent<Integer> taking the value 0 in case of success and 1 in case
* of failure.
* @param context the Context of the caller
* @return logInResult SingleLiveEvent<Integer> result of the try
*/
@Override
public SingleLiveEvent<Integer> tryToLog(Context context, String email, String password,
boolean isKeepLogged) {
SingleLiveEvent<Integer> logInResult = new SingleLiveEvent<>();
Disposable disposable = pfcRepository.getUserByEmail(email).subscribe(
user -> CryptographyUtils.checkPassword(password, user.getPassword()).subscribe(
() -> {
pfcRepository.setUserLogged(user);
if (isKeepLogged) {
setAutoLogin(context);
}
logInResult.setValue(0);
Log.i(TAG, "Log in success.");
}, throwable -> {
logInResult.setValue(1);
Log.i(TAG, "Log in failure, wrong password.");
}),
throwable -> {
logInResult.setValue(1);
Log.e(TAG, "Log in failure ", throwable);
});
addToCompositeDisposable(context, disposable);
return logInResult;
}
...
宠物食品控制服务
public abstract class PetFoodingControlService {
/** Disposable management */
protected final Map<Context, CompositeDisposable> compositeDisposableMap = new HashMap<>();
/**
* Add the Disposable to the CompositeDisposable corresponding to the context.
* @param context the context of the CompositeDisposable
* @param disposable the Disposable to add
*/
protected final void addToCompositeDisposable(Context context, Disposable disposable) {
if (!compositeDisposableMap.containsKey(context)) {
compositeDisposableMap.put(context, new CompositeDisposable());
}
compositeDisposableMap.get(context).add(disposable);
}
/**
* Clear the CompositeDisposable corresponding to the context given in parameter,
* if it exists in the storage map.
* @param context the context of th CompositeDisposable
*/
protected final void compositeDisposableClear(Context context) {
if (compositeDisposableMap.containsKey(context)) {
compositeDisposableMap.get(context).clear();
}
}
PetFoodingControlRepositoryImpl
@RepositoryScope
public class PetFoodingControlRepositoryImpl implements PetFoodingControlRepository {
private static final String DB_NAME = "pfc_db";
private final PetFoodingControlDatabase petFoodingControlDatabase;
private final MutableLiveData<User> userLogged = new MutableLiveData<>();
private final MutableLiveData<Pet> userPets = new MutableLiveData<>();
@Inject
public PetFoodingControlRepositoryImpl(Application application) {
petFoodingControlDatabase = Room.databaseBuilder(application, PetFoodingControlDatabase.class, DB_NAME).build();
}
@Override
public Single<User> getUserByEmail(String email) {
return petFoodingControlDatabase.getUserDao().getUserByEmail(email)
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread());
}
@Override
public Single<User> getUserById(Long userId) {
return petFoodingControlDatabase.getUserDao().getUserById(userId)
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread());
}
@Override
public Single<Photo> getUserPhoto(User user) {
return petFoodingControlDatabase.getPhotoDao().getPhotoById(user.getPhotoId())
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread());
}
@Override
public void setUserLogged(User user) {
userLogged.setValue(user);
}
@Override
public MutableLiveData<User> getUserLogged() {
return userLogged;
}
...
最佳答案
你的问题是这一行:
userService.getPfcRepository().getUserLogged().observe(this, user -> {
您的this是它所在的 Activity - 或者更确切地说是它的生命周期。 一旦 Activity 暂停,监听器就会默认被删除。
要克服这个问题,您有两个选择:
- 在onResume中注册这一行,并接收值,因为有 是一个值
- 向不是您 Activity 生命周期的 LifeCycleOwner 注册此行。
关于java - 为什么主要 Activity 没有触发监听器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59862675/