Совместное использование и доступ к текстовому значению переключателя между двумя файлами kotlin

#android #android-studio #android-layout #kotlin #android-fragments

#Android #android-studio #android-макет #kotlin #android-фрагменты

Вопрос:

У меня есть приложение, которое начинается с 2 переключателей.

Когда я нажимаю на один из них, я могу восстановить его текстовое значение в текущем файле. Но когда я пытаюсь получить доступ к этому значению в другом файле, оно не меняется, даже если я нажимаю на другую кнопку!!

MainActivity.kt

 class MainActivity : AppCompatActivity() {
public var rbt= "French"
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.layout_activity_main)

    window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)

    val assistantFragment = AimyboxAssistantFragment()

    supportFragmentManager.beginTransaction().apply {

        replace(R.id.assistant_container, assistantFragment)
        commit()
    }

}
// Get the selected radio button text using radio button on click listener
fun radio_button_click(view: View){
    // Get the clicked radio button instance
    val radio: RadioButton = findViewById(radio_group.checkedRadioButtonId)
    rbt=radio.text.toString()
    Toast.makeText(applicationContext,"On click : ${rbt}",
        Toast.LENGTH_SHORT).show()
}
override fun onBackPressed() {
    val assistantFragment = (supportFragmentManager.findFragmentById(R.id.assistant_container)
            as? AimyboxAssistantFragment)
    if (assistantFragment?.onBackPressed() != true) super.onBackPressed()
}
  

}

Другой файл (AimyboxApplication.kt), в котором я хочу получить доступ к текстовому значению переключателя :

 class AimyboxApplication : Application(), AimyboxProvider {

companion object {
    private const val AIMYBOX_API_KEY = ""
}

override val aimybox by lazy { createAimybox(this) }

private fun createAimybox(context: Context): Aimybox {
    val unitId = UUID.randomUUID().toString()
    val textToSpeech = GooglePlatformTextToSpeech(context, Locale.getDefault())
    val speechToText = GooglePlatformSpeechToText(context, Locale.getDefault())
    //speechToText.toString()
    var rbt = MainActivity().rbt

    if (rbt=="English"){
        println("English")
    }
    if (rbt=="French"){
        println("French")
    }
    // Do something
}
  

}

layout_activity_main.xml

 <?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

<ImageView
        android:layout_width="wrap_content"
        android:layout_height="200dp"
        android:layout_gravity="center"
        android:layout_marginBottom="100dp"
        android:src="@mipmap/logo"/>

<RadioGroup
    android:id="@ id/radio_group"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:layout_marginTop="100dp"
    android:checkedButton="@ id/fr">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:layout_marginTop="100dp"
        android:padding="18dp"
        android:text="@string/prompt"
        android:textSize="22sp" />

    <RadioButton
        android:id="@ id/en"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="English"
        android:onClick="radio_button_click"/>

    <RadioButton
        android:id="@ id/fr"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="French"
        android:onClick="radio_button_click"/>


</RadioGroup>

<FrameLayout
    android:id="@ id/assistant_container"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />


</FrameLayout>
  

Когда я запускаю приложение, оно всегда выводит меня на «французский», даже если я нажал на английскую кнопку переключения!!

Спасибо.

Комментарии:

1. Вы оставили ключ API во вставленном коде, на всякий случай, если это проблема

Ответ №1:

Рассмотрим эти вещи:

  1. В createAimybox методе и этом коде MainActivity().rbt этот код создаст новый экземпляр MainActivity , и в этом заданном вами действии public var rbt= "French" . Вот почему это French значение для печати.
  2. AimyboxApplication класс будет вызываться перед началом действия, поскольку это приложение, также этот класс будет вызываться только один раз. Итак, теперь, даже если вы измените значение внутри MainActivity , метод класса приложения не будет запущен автоматически (также это другой объект MainActivity), вам нужно ввести некоторую логику. Но не рекомендуется использовать такую логику на уровне приложения, поскольку она будет меняться.

Редактировать:

Позвольте мне дать вам простое решение для этого:

Сначала добавьте этот LanguagePref класс.

 import android.content.Context
import android.content.SharedPreferences
const val LANGUAGE_PREFERENCE = "preferenceData"
const val LANGUAGE_DATA = "languageData"

public enum class LANGUAGE_ENUM(languageCode:String){
     ENGLISH("English"),
     FRENCH("French")
}

public class LanguagePref(val context: Context) {
    private val mPreferences: SharedPreferences by lazy {
        context.getSharedPreferences(
            LANGUAGE_PREFERENCE,
            Context.MODE_PRIVATE
        )
    }
    private val mEditor: SharedPreferences.Editor by lazy { mPreferences.edit() }

    public fun saveLanguage(
        langauage: String
    ) {
        mEditor
            .putString(LANGUAGE_DATA, langauage)
            .apply()
    }

    public fun getLanaguage(): String {
        return mPreferences.getString(LANGUAGE_DATA, LANGUAGE_ENUM.ENGLISH.name)!!
    }
}
  

Теперь в вашем основном действии внутри события нажатия кнопки вы можете сохранить язык следующим образом:

 val languagePref =LanguagePref(this)
languagePref.saveLanguage(LANGUAGE_ENUM.ENGLISH.name)
//languagePref.saveLanguage(LANGUAGE_ENUM.FRENCH.name)//For FRENCH language
  

Также вы должны использовать aimybox и createAimybox внутри MainActivity , а не на уровне приложения:

  override val aimybox by lazy { createAimybox(this) }

    private fun createAimybox(context: Context): Aimybox {
        val unitId = UUID.randomUUID().toString()

        val textToSpeech = GooglePlatformTextToSpeech(context, Locale.ENGLISH)
        val speechToText = GooglePlatformSpeechToText(context, Locale.ENGLISH)

        val dialogApi = AimyboxDialogApi(AIMYBOX_API_KEY, unitId)
        var rbt = LanguagePref(this).getLanaguage()

        if (rbt==LANGUAGE_ENUM.ENGLISH.name){
            println("English")
        }
        if (rbt==LANGUAGE_ENUM.FRENCH.name){
            println("French")
        }
        return Aimybox(Config.create(speechToText, textToSpeech, dialogApi))
    }
  

Потому что код уровня приложения не будет вызываться снова. Также это упоминается в Aimybox документе. Вы можете проверить это с помощью, (CTRL Right click) aimybox внутри AimyboxApplication класса, и он откроет этот интерфейс:

 /**
 * Implement the interface in your Activity or Application to start using Aimybox components
 * */
interface AimyboxProvider {
    /**
     * Main class of the Aimybox library. You should have only one instance of the class for correct behavior.
     * */
    val aimybox: Aimybox
    /**
     *
     * */
    fun getViewModelFactory() = AimyboxAssistantViewModel.Factory.getInstance(aimybox)
}
  

Если вы посмотрите на комментарий, в нем говорится Activity or Application :

 /**
 * Implement the interface in your Activity or Application to start using Aimybox components
 * */
  

Комментарии:

1. Спасибо @keyur за ваш ответ. Итак, что вы предлагаете?

2. То, что вы хотите сделать, зависит от ваших требований. Пожалуйста, объясните, что именно вы хотите сделать.

3. то, что я хочу сделать, просто. При запуске приложения я выбираю язык, нажимая на один переключатель, а затем я хочу получить текстовое значение переключателя, нажатого в файле AimyboxApplication.kt точно в методе createAimybox ()

Ответ №2:

Keyur прав в отношении значения, вы не получаете доступ к тому, которое вы сохранили, вы создаете совершенно новое действие со значением по умолчанию ( "French" ), так что это то, что вы читаете.

У вас есть несколько вариантов, в зависимости от того, как настроено ваше приложение. Проще всего просто вызвать createAimybox() напрямую, когда язык установлен, и передать язык в качестве параметра. Если вы делаете это между действиями (вместо того, чтобы хранить его в приложении), вы должны передавать данные в качестве дополнительных в Intent пакете.

Возможно, было бы лучше сохранить его SharedPreferences и указать цели захватить текущее значение — таким образом createAimybox , функция может просто посмотреть, какова текущая настройка, и она будет сохраняться и между сеансами приложения, если это важно.

Я предполагаю, что aimybox lazy это свойство инициализируется после того, как пользователь устанавливает свой язык, но затем оно навсегда фиксируется до тех пор, пока приложение не будет закрыто и перезапущено. Поэтому, если вы хотите, чтобы пользователь мог менять язык без перезапуска приложения, вам нужно будет действовать по-другому.

Комментарии:

1. да @cactustictacs. я новичок в Android. можете ли вы сказать мне, где и как я могу вызвать createAimybox() напрямую, когда язык установлен?