Плавающая кнопка не работает при маршрутизации на контроллер проводника во второй раз
Я использую проводник и нож.
У меня есть BaseController, где я делаю шаблон BN:
protected ButterKnifeController() { }
protected ButterKnifeController(Bundle args) {
super(args);
}
protected abstract View inflateView(@NonNull LayoutInflater inflater, @NonNull ViewGroup container);
@NonNull
@Override
protected View onCreateView(@NonNull LayoutInflater inflater, @NonNull ViewGroup container) {
View view = inflateView(inflater, container);
unbinder = ButterKnife.bind(this, view);
onViewBound(view);
return view;
}
protected void onViewBound(@NonNull View view) { }
@Override
protected void onDestroyView(@NonNull View view) {
super.onDestroyView(view);
unbinder.unbind();
unbinder = null;
}
}
У меня есть пара контроллеров с FAB в них, хотя проблема с простыми кнопками та же.
Когда я в первый раз направляюсь к контроллеру, onClick() работает как положено. Но когда я направляю к контроллеру во второй раз, onClick() не делает.
Вот пример двух контроллеров, первый из которых я хочу перенаправить обратно:
WelcomeController - Fab отлично работает, когда я впервые здесь
public class WelcomeController extends BaseController {
@BindView(R.id.tv_step_title)
TextView title;
@BindView(R.id.tv_step_message)
TextView message;
@Override
protected View inflateView(@NonNull LayoutInflater inflater, @NonNull ViewGroup container) {
return inflater.inflate(R.layout.controller_base_title_text, container, false);
}
@Override
protected void onViewBound(@NonNull View view) {
super.onViewBound(view);
title.setText(getResources().getText(R.string.wizard_welcome_step_title));
message.setText(getResources().getText(R.string.wizard_welcome_step_message));
}
@Override
protected void onAttach(@NonNull View view) {
super.onAttach(view);
requestVideoPermissions();
}
@OnClick(R.id.fab_next)
public void onFabNextClick(){
getRouter().pushController(RouterTransaction.with(new DiagnosePulseController())
.pushChangeHandler(new FadeChangeHandler())
.popChangeHandler(new FadeChangeHandler()));
}
}
SecondController - Нажатие на все Fab-маршруты allDone в WelcomeController, но события onClick() не запускаются.
public class RecordFingertPulseController extends BaseController {
private static final String TAG = RecordFingertPulseController.class.getSimpleName();
public static final String WRIST_PPG_KEY = "wrist_ppg";
public static final String WRIST_TS_KEY = "wrist_ts";
private CameraController mCameraController;
private static final PpgRecordedRxModel PPG_RX_MODEL = PpgRecordedRxModel.getInstance();
private PulseModel mPulseModel = null;
private final CameraController.Callback mRxCameraControllerCallback = new CameraController.Callback() {
@Override
public void onCameraAccessException() {
Log.e(TAG, "CameraAccessException");
}
@Override
public void onCameraOpenException(@Nullable OpenCameraException.Reason reason) {
Log.e(TAG, new OpenCameraException(reason).getMessage());
}
@Override
public void onException(Throwable throwable) {
Log.e(TAG, throwable.getMessage());
}
};
@BindView(R.id.fab_record_pulse)
FloatingActionButton mFabRecordPulse;
@BindView(R.id.fab_all_done)
FloatingActionButton mFabAllDone;
@BindView(R.id.tv_step_title)
MyTextView tv_title;
@BindView(R.id.tv_step_message)
MyTextView tv_message;
public RecordFingertPulseController(Bundle dataBundle) {
super(dataBundle);
}
@Override
protected View inflateView(@NonNull LayoutInflater inflater, @NonNull ViewGroup container) {
return inflater.inflate(R.layout.controller_pulse_recording, container, false);
}
@NonNull
@Override
protected View onCreateView(@NonNull LayoutInflater inflater, @NonNull ViewGroup container) {
return super.onCreateView(inflater, container);
}
@Override
protected void onAttach(@NonNull View view) {
super.onAttach(view);
setupViews();
//Analytics screws camera FPS
FirebaseAnalytics.getInstance(getActivity()).setAnalyticsCollectionEnabled(false);
startCamera();
mCameraController.getConductorLifecycle().onAttach();
subscribeToPpgRecorded();
}
private void subscribeToPpgRecorded() {
PPG_RX_MODEL.getPpgObservable()
.doOnNext(ppg -> Log.d(TAG, "PulseModel before filter :\t"
+ ppg.getPulseName() + "\nPulseModel wrist ppg size"
+ ppg.getWrisrPpgList().size()
+ "\nPulseModel finger ppg size: " + ppg.getFingerPpgList().size()))
.filter(ppg -> ppg.getWrisrPpgList().size() > 0
&& ppg.getFingerPpgList().size() > 0)
.doOnNext(ppg -> Log.d(TAG, "Got PulseModel() after filter with finger ppg size: "
+ ppg.getFingerPpgList().size() + "\twrist ppg size: "
+ ppg.getWrisrPpgList().size()))
.subscribe(ppg -> finalizeWristRecording(ppg));
}
private void finalizeWristRecording(PulseModel ppg) {
// mFabRecordPulse.setEnabled(true);
mFabAllDone.setVisibility(View.VISIBLE);
try {
mPulseModel = ppg.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
Log.d(TAG, "Got the ppg with size: " + ppg.getWrisrPpgList().size());
}
private void startCamera() {
CameraManager cameraManager = (CameraManager) getActivity().getSystemService(Context.CAMERA_SERVICE);
String cameraId = null;
CameraCharacteristics characteristics = null;
Size videoSize = null;
try {
cameraId = cameraManager.getCameraIdList()[0];
characteristics = cameraManager.getCameraCharacteristics(cameraId);
} catch (CameraAccessException e) {
e.printStackTrace();
}
StreamConfigurationMap map = characteristics
.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
if (map == null) {
throw new RuntimeException("Cannot get available preview/video sizes");
}
videoSize = MyUtils.chooseVideoSize(map.getOutputSizes(ImageReader.class));
mCameraController = new CameraController(getActivity(), mRxCameraControllerCallback,
cameraManager, cameraId, videoSize, CameraController.PpgSource.FINGER);
}
@Override
protected void onDetach(@NonNull View view) {
mCameraController.getConductorLifecycle().onDetach();
mCameraController.getCameraClosedObservable().blockingLast();
super.onDetach(view);
}
private void setupViews() {
mFabAllDone.setVisibility(View.GONE);
tv_title.setText(R.string.wizard_record_finger_pulse_step_title);
tv_message.setText(R.string.wizard_record_finger_pulse_step_message);
mFabAllDone.setImageResource(R.drawable.ic_done_all_white_24dp);
}
@OnClick(R.id.fab_record_pulse)
public void onRecordPulseClick(){
mFabRecordPulse.setEnabled(false);
mCameraController.recordPulseClick();
}
@OnClick(R.id.fab_all_done)
public void onAllDoneClick(){
if(mPulseModel.getFingerPpgList().size() > 0 || mPulseModel.getWrisrPpgList().size() > 0){
PulseFirebaseRepository.getRepoInstance().create(mPulseModel);
requestVideoPermissions();
mPulseModel.savePpg();
getRouter().pushController(RouterTransaction.with(new WelcomeController())
.pushChangeHandler(new FadeChangeHandler())
.popChangeHandler(new FadeChangeHandler()));
}else{
if(null != getActivity()){
new AlertDialog.Builder(getActivity())
.setMessage(R.string.empty_pulse_error)
.setPositiveButton(android.R.string.ok, null)
.show();
}
}
}
}
Я просто не могу понять, почему. И это похоже на проблему BN. Любая помощь будет оценена.
2 ответа
Я подозреваю, что ваша проблема связана с тем, как вы вернетесь к WelcomeController. Ваш текущий код создает новый WelcomeController, когда onAllDoneClick()
называется. В конце концов, у вас есть WelcomeController, покрытый RecordFingerPulseController, покрытый другим WelcomeController.
Вы уже настроили обратный переход в onFabNextClick()
где вы добавили popChangeHandler
,
Самый простой способ вернуться - позвонить getRouter().popCurrentController();
вместо добавления нового WelcomeController поверх RecordFingerPulseController. Это оставит вас только с WelcomeController.
Если вы посмотрите на реализацию маршрутизатора, вы обнаружите, что он имеет popToRoot(...)
метод. Это должно удалить все из заднего стека. Вот метод и его комментарий:
/**
* Pops all {@link Controller}s until only the root is left
*
* @return Whether or not any {@link Controller}s were popped in
* order to get to the root transaction
*/
@UiThread
public boolean popToRoot() {
ThreadUtils.ensureMainThread();
return popToRoot(null);
}
Есть несколько других способов решения проблемы.
- Если вы не собираетесь возвращаться назад через стек, вы можете заменить контроллер вместо установки нового.
- Вы можете добавить теги использования вместе с
popToTag(...)
размотать стек на желаемый контроллер. - Вы можете получить задний стек в виде списка, используя
getBackstack()
а затем манипулировать вещами, используя эту информацию. - И т.п.