0

I have two classes AdminPinActivity.kt and AdminPinActivityPresenter.kt

AdminPinActivity.kt:

  class AdminPinActivity : InjectableAppCompatActivity() {
  @Inject
  lateinit var adminPinActivityPresenter: AdminPinActivityPresenter
  private var input_Pin: String = ""
  private var input_Confirm_Pin: String = ""

  companion object {
    fun createAdminPinActivityIntent(context: Context, profileId: Int, colorRgb: Int): Intent {
      val intent = Intent(context, AdminPinActivity::class.java)
      intent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY)
      intent.putExtra(KEY_ADMIN_PIN_PROFILE_ID, profileId)
      intent.putExtra(KEY_ADMIN_PIN_COLOR_RGB, colorRgb)
      return intent
    }
  }

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    activityComponent.inject(this)

    adminPinActivityPresenter.handleOnCreate(savedInstanceState)
  }

  override fun onSaveInstanceState(outState: Bundle) {
    adminPinActivityPresenter.handleOnSavedInstanceState(outState)
    super.onSaveInstanceState(outState)
  }

  override fun onSupportNavigateUp(): Boolean {
    finish()
    return false
  }
}

AdminPinActivityPresenter.kt:

    /** The presenter for [AdminPinActivity]. */
@ActivityScope
class AdminPinActivityPresenter @Inject constructor(
  private val context: Context,
  private val activity: AppCompatActivity,
  private val profileManagementController: ProfileManagementController,
  private val viewModelProvider: ViewModelProvider<AdminPinViewModel>
) {
  private val adminViewModel by lazy {
    getAdminPinViewModel()
  }

  private var input_Pin: String = ""
  private var input_Confirm_Pin: String = ""

  /** Binds ViewModel and sets up text and button listeners. */
  fun handleOnCreate(savedInstanceState: Bundle?) {
    activity.title = activity.getString(R.string.add_profile_title)
    activity.supportActionBar?.setDisplayHomeAsUpEnabled(true)
    activity.supportActionBar?.setHomeAsUpIndicator(R.drawable.ic_close_white_24dp)

    val binding =
      DataBindingUtil.setContentView<AdminPinActivityBinding>(activity, R.layout.admin_pin_activity)

    binding.apply {
      lifecycleOwner = activity
      viewModel = adminViewModel
    }               

    if (savedInstanceState != null) {

      if (savedInstanceState.getString("InputPin") != null) {
        Log.i("Input pin from savedInstanceState",savedInstanceState.getString("InputPin"))
        binding.inputPin.input.setText(savedInstanceState.getString("InputPin"))

      }
      if (savedInstanceState.getString("InputConfirmPin") != null) {
        binding.inputConfirmPin.input.setText(savedInstanceState.getString("InputConfirmPin"))
      }
      binding.executePendingBindings()
    }       

      binding.inputPin.addTextChangedListener(object :TextWatcher{
      override fun afterTextChanged(p0: Editable?) {}

      override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
      }
      override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
        input_Pin=p0.toString().trim()
      }
    })

    binding.inputConfirmPin.addTextChangedListener(object : TextWatcher {
      override fun afterTextChanged(p0: Editable?) {
        input_Confirm_Pin=p0.toString().trim()
      }

      override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
      }

      override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
      }
    })




  }

  fun handleOnSavedInstanceState(bundle: Bundle) {    
    bundle.putString("InputPin", input_Pin)
    Log.i("input_Pin",input_Pin)
    bundle.putString("InputConfirmPin", input_Confirm_Pin)    
  }


  private fun getAdminPinViewModel(): AdminPinViewModel {
    return viewModelProvider.getForActivity(activity, AdminPinViewModel::class.java)
  }
}

Log.i("Input pin from savedInstanceState",savedInstanceState.getString("InputPin")) and Log.i("input_Pin",input_Pin) are getting logged on every rotation. That means the code is working fine, but the EditText values are not getting updated i.e. binding.inputPin.input.setText(savedInstanceState.getString("InputPin")) and binding.inputConfirmPin.input.setText(savedInstanceState.getString("InputConfirmPin")) are not working properly.

When I use binding.inputPin.input.setText("Something") outside the if statements i.e inside the handleOnCreateMethod then it is updating the EditText Value with "Something" once. But on screen rotation that is lost too.

I hope you understand the question.

I have searched everywhere for almost two days now and can't find the solution to it. I don't want to use the Two-Way data binding.

admin_pin_activity.xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:app="http://schemas.android.com/apk/res-auto"
  xmlns:profile="http://schemas.android.com/tools">
  <data>
    <variable
      name="viewModel"
      type="org.oppia.app.profile.AdminPinViewModel" />
  </data>
  <ScrollView
    android:id="@+id/scrollViewAdminPin"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/addProfileBackground">
    <androidx.constraintlayout.widget.ConstraintLayout
      android:id="@+id/admin_auth_container"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:background="@color/addProfileBackground">
      <TextView
        android:id="@+id/admin_pin_main_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/admin_pin_requirement_description"
        android:textColor="@color/oppiaPrimaryText"
        android:textSize="16sp"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        android:layout_marginTop="32dp"
        android:paddingStart="32dp"
        android:paddingEnd="32dp"/>
      <TextView
        android:id="@+id/admin_pin_warning_text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/admin_pin_pin_description"
        android:textSize="16sp"
        android:textColor="@color/oppiaPrimaryText"
        app:layout_constraintTop_toBottomOf="@+id/admin_pin_main_text"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        android:layout_marginTop="16dp"
        android:paddingStart="32dp"
        android:paddingEnd="32dp"/>
      <org.oppia.app.profile.ProfileInputView
        android:id="@+id/input_pin"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        app:layout_constraintTop_toBottomOf="@+id/admin_pin_warning_text"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:label="@string/admin_pin_new_pin"
        app:isPasswordInput="true"
        app:inputLength="5"
        profile:error="@{viewModel.pinErrorMsg}"/>
      <org.oppia.app.profile.ProfileInputView
        android:id="@+id/input_confirm_pin"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toBottomOf="@+id/input_pin"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:label="@string/admin_pin_new_confirm"
        app:isPasswordInput="true"
        app:inputLength="5"
        profile:error="@{viewModel.confirmPinErrorMsg}"/>
      <Button
        android:id="@+id/submit_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/admin_pin_submit"
        style="@style/StateButtonActive"
        app:layout_constraintTop_toBottomOf="@+id/input_confirm_pin"
        app:layout_constraintEnd_toEndOf="parent"
        android:layout_marginTop="20dp"
        android:layout_marginEnd="32dp"/>
    </androidx.constraintlayout.widget.ConstraintLayout>
  </ScrollView>
</layout>

profile_input_view.xml:

<?xml version="1.0" encoding="utf-8"?>
<layout>

  <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginStart="28dp"
    android:layout_marginTop="32dp"
    android:layout_marginEnd="28dp"
    android:descendantFocusability="beforeDescendants"
    android:focusableInTouchMode="true"
    android:orientation="vertical">

    <TextView
      android:id="@+id/label_text"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_marginStart="4dp"
      android:fontFamily="sans-serif"
      android:textAllCaps="true"
      android:textColor="@color/oppiaPrimaryText"
      android:textSize="12sp" />

    <EditText
      android:id="@+id/input"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:layout_marginTop="4dp"
      android:background="@drawable/add_profile_edit_text_background"
      android:fontFamily="sans-serif"
      android:padding="8dp"
      android:textColor="@color/oppiaPrimaryText"
      android:textSize="14sp"
      android:textStyle="italic" />

    <TextView
      android:id="@+id/error_text"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:textColor="@color/red" />
  </LinearLayout>
</layout>
NullByte08
  • 884
  • 10
  • 15
  • In onSaveInstanceState() , call the super before handleOnSavedInstanceState(). – Cheticamp 12 mins ago – Cheticamp Mar 13 '20 at 14:29
  • Also, make sure to call the super for restoring the instance state before modifying you edit text values. I think that the framework is overwriting your changing. By changing the order, you will overwrite the frameworks changes instead which is what you want. – Cheticamp Mar 13 '20 at 14:35
  • I called the onrestoreinstancestate method, but for some reason , edittext is only being retained for input in the inputconfirmpin edittext and not the inputpin edittext. – NullByte08 Mar 13 '20 at 14:48
  • I think this is the right track. You don't need to save/restore _EditTexts_ at all since Android does that for you. (Not all views, but definitely _EditText_.) If you do need to save/restore an _EditText_, continue to look at the sequencing and exercise the debugger to get a handle on what is going on. If that doesn't work, you may need to wait for someone to do a complete answer – Cheticamp Mar 13 '20 at 14:56
  • I wrote an answer please check. – NullByte08 Mar 13 '20 at 14:58
  • Android is not retaining edittext on its own. I tried that too :/ – NullByte08 Mar 13 '20 at 14:59
  • OK. Not sure what is going on. Your answer is not really an answer. I would delete it. (It may be deleted by the moderators anyway.) I think you are more likely to get a response if there is not an answer. – Cheticamp Mar 13 '20 at 15:01
  • You don't seem to use two-way binding. Can you show your XML layout and the binding code it contains? Probably that when you call `executePendingBindings()` the binding will overwrite the text you set manually with whichever source you use. – BladeCoder Mar 18 '20 at 15:32
  • I have tried my code without using `executePendingBindings()` too. It shows the same result. And also I am not using two way binding. Actually I have a customview so there is no attribute like `android:text` which I can use for one of the endpoints of two way binding. – NullByte08 Mar 18 '20 at 15:41
  • I tried adding the attribute( in the attrs) but my customview was not rendering, and I skipped the idea of two way binding. – NullByte08 Mar 18 '20 at 15:42
  • @Cheticamp I think I have figured it out. I was using a customView called ProfileInputView. It itself has an EditText inside it. That means every instance of that ProfileInputVie has same id for that EditText.That means that every instance will contain the same value for the text field......Is there any way I can give unique id to EditText for each instance of ProfileInputView. – NullByte08 Mar 18 '20 at 16:45
  • @BladeCoder Can you please take a look too – NullByte08 Mar 18 '20 at 16:47
  • 1
    You should preferably let the views restore their own state instead of doing it manually. If you have a custom view containing other views then you need to implement your own code for saveInstanceState and restoreInstanceState in the custom view and disable automatic state restoration for inner views using `android:saveEnabled="false"`. – BladeCoder Mar 18 '20 at 16:58
  • 1
    I agree with @BladeCoder and that will be the best approach. You could also try assigning a unique id to the _EditText_ field within your custom view using _View.generateId()_. You would have to work out the particulars. – Cheticamp Mar 18 '20 at 22:22
  • @BladeCoder Thank you so much dude. You solved it. Cheticamp thank you for helping too. – NullByte08 Mar 19 '20 at 09:15

0 Answers0