java - 为什么主要 Activity 没有触发监听器?

标签 java android

我有一个主要 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 暂停,监听器就会默认被删除。

要克服这个问题,您有两个选择:

  1. 在onResume中注册这一行,并接收值,因为有 是一个值
  2. 向不是您 Activity 生命周期的 LifeCycleOwner 注册此行。

关于java - 为什么主要 Activity 没有触发监听器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59862675/

相关文章:

android - Android Studio 中缺少 android.os.handler 对象

java - 无法解析符号 'v' 和预期的 ) 和 ;

c# - 如何在 Windows 中的那个时刻查找特定进程的 cpu 使用率

java - 如何根据这种特殊的 equals 逻辑重写 hashcode 方法

java - httpClient:如何检查连接是否已被服务器端关闭

Android,如何获取Facebook/Twitter/等联系人照片

javascript - 谁能帮我分离世博会应用程序

android - 在哪里可以找到 Google Play Developer Console : Crashes & ANRs? 的设备型号

java - 在单元测试期间重置类静态变量

android - 将长整数数组从 C 返回到 Java