Categories
discuss

Kotlin Set Global Variable in Global Class

I’m new to Kotlin. And I need a help that I can’t understand to java and kotlin.

For Java I made it. But for kotlin I can’t The thing is, I create a Global kotlin class public class Global : Application()

In MainFest I declared that android:name=”.Global”

and in Global Class I declared a variable:

public class Global : Application() {
    open var homeAPIResponse: String = "defaultValue"
}

When I set to this global variable any value, it’s won’t save and when I fetch the value always it’s showing default value. I can’t understand the java type getter and setter methods in kotlin. Please help me.

I tried that:

global = Global()
global.homeAPIResponse  = "2nd Text"

Log.d("testingTag", "Testing modified response >>>> " + global.homeAPIResponse)

In log it’s always showing the defaultvalue.

========================================================================= Guys, my purpose is to save some value globally that, after moves one activity to another, the value will not erase.

Please help me with proper described example cause I searched a lot on stack overflow. and coudn’t get it.

Thanks in Advance

Answer

Maybe try like this:

public class Global : Application() {
    companion object {
        @JvmField
        var homeAPIResponse: String = "defaultValue"
    }
}

In other activity:

Global.homeAPIResponse = "new value"
Categories
discuss

In Spring Kafka, do I need to add the @EnableKafka annotation to my application?

I see some people adding @EnableKafka to their spring boot application and I was wondering why. I have a working spring boot kafka producer and consumer and I didn’t use @EnableKafka. So, why do people need to add it explicitly?

Thank you.

Answer

That is because Spring boot provides an auto configuration for Kafka via KafkaAutoConfiguration class (javadoc). When you use @EnableAutoConfiguration or @SpringBootApplication, Spring boot automatically configures Kafka for you.

You can test that by excluding the auto configuration by providing @SpringBootApplication(exclude={KafkaAutoConfiguration.class}), and Spring boot would not automatically configure Kafka for you.

If you don’t use Spring boot, then you would have to use @EnableKafka to configure Kafka for your Spring app.

Categories
discuss

Android how to use Kotlin-Coroutine in Java?

Recently I am learning kotlin-coroutine by following this CodeLabs tutorial. After some hands on, I was wondering if I could the same code in java. So first I wrote a simple kotlin code in MyKotlinFragment.kt file like this:

import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch

// ... some codes

    private fun myKoroutineDemo(){
        GlobalScope.launch {
            val result1:Int = foo();
            val result2:Int = bar();
            val result3 = result1 + result2;
            Log.e(TAG, ""+result3);
        }
    }

    suspend fun foo():Int{
        delay(2000);
        var result = 2+2;
        delay(500);
        return result;
    }

    suspend fun bar():Int{
        delay(2000);
        var result = 7-2;
        delay(500);
        return result;

    }

And called myKotlinDemo() in my fragment; it works.

Next I opended a java file named MyCoroutineFragment.java in the same project but I can’t make it work.

import kotlinx.coroutines.delay;     
import kotlinx.coroutines.launch;   // delay and launch imports arenot fount and so they are red

private suspend int foo(){ return 2 + 2; }
// the `suspend` keyword is not found by android studio, same with the bar method

private void myCoroutineDemo(){
  // GlobalScope.launch don't show up here, 
}

I can’t convert the first file into Java. How can I fix this?

If it is impossible to convert, why and how else can I use coroutine in Java?

Answer

For coroutines in Java question, check this question on stackOverflow.

But in my hummble opinion, use other tools for asynchronous call (e.g. RXjava). You gonna suffer from callbacks but I think it will be fine.

But be aware not to use AsyncTask as it’s now deprecated.

Categories
discuss

Live data giving old value again while changing fragment

I am using live data from a shared ViewModel across multiple fragments. I have a sign-in fragment which takes user’s phone number and password and then the user presses sign in button I am calling the API for that, now if the sign-in fails I am showing a toast “Sign In failed”, now if the user goes to “ForgotPassword” screen which also uses the same view model as “SignInFragment” and presses back from the forgot password screen, it comes to sign-in fragment, but it again shows the toast “Sign In failed” but the API is not called, it gets data from the previously registered observer, so is there any way to fix this?

SignInFragment.kt

class SignInFragment : Fragment() {

    private lateinit var binding: FragmentSignInBinding

    //Shared view model across two fragments
    private val onBoardViewModel by activityViewModels<OnBoardViewModel>()

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        binding = DataBindingUtil.inflate(
            inflater,
            R.layout.fragment_sign_in,
            container,
            false
        )
        return binding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        onBoardViewModel.signInResponse.observe(viewLifecycleOwner) { response ->
            //This is calling again after coming back from new fragment it.
            showToast("Sign In Failed")
        }
    }

    override fun onClick(v: View?) {
        when (v?.id!!) {
            R.id.forgotPasswordTV -> {
                findNavController().navigate(SignInFragmentDirections.actionSignInFragmentToForgotPasswordFragment())
            }
            R.id.signInTV -> {
                val phoneNumber = binding.phoneNumberET.text
                val password = binding.passwordET.text
                val signInRequestModel = SignInRequestModel(
                    phoneNumber.toString(),
                    password.toString(),
                    ""
                )

                //Calling API for the sign-in
                onBoardViewModel.callSignInAPI(signInRequestModel)
            }
        }
    }
}

ForgotPasswordFragment

class ForgotPasswordFragment : Fragment() {

    private lateinit var binding: FragmentForgotPasswordBinding

    //Shared view model across two fragments
    private val onBoardViewModel by activityViewModels<OnBoardViewModel>()

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        binding = DataBindingUtil.inflate(
            inflater,
            R.layout.fragment_forgot_password,
            container,
            false
        )
        return binding.root
    }
}

OnBoardViewModel

class OnBoardViewModel : ViewModel() {

    private var repository: OnBoardRepository = OnBoardRepository.getInstance()

    private val signInRequestLiveData = MutableLiveData<SignInRequestModel>()

    //Observing this data in sign in fragment
    val signInResponse: LiveData<APIResource<SignInResponse>> =
        signInRequestLiveData.switchMap {
            repository.callSignInAPI(it)
        }

    //Calling this function from sign in fragment
    fun callSignInAPI(signInRequestModel: SignInRequestModel) {
        signInRequestLiveData.value = signInRequestModel
    }

    override fun onCleared() {
        super.onCleared()
        repository.clearRepo()
    }
}

I have tried to move this code inside onActivityCreated but it’s still getting called after coming back from new fragment.

 onBoardViewModel.signInResponse.observe(viewLifecycleOwner) { response ->
            showToast("Sign In Failed")
        }

Answer

Using SingleLiveEvent class instead of LiveData in OnBoardViewModel class will solve your problem:

val signInResponse: SingleLiveEvent <APIResource<SignInResponse>>.

class SingleLiveEvent<T> : MutableLiveData<T>() {

    private val pending = AtomicBoolean(false)

    override fun observe(owner: LifecycleOwner, observer: Observer<in T>) {
        super.observe(owner, Observer<T> { t ->
            if (pending.compareAndSet(true, false)) {
                observer.onChanged(t)
            }
        })
    }

    override fun setValue(t: T?) {
        pending.set(true)
        super.setValue(t)
    }

    fun call() {
        postValue(null)
    }

}

This is a lifecycle-aware observable that sends only new updates after subscription. This LiveData only calls the observable if there’s an explicit call to setValue() or call().

Categories
discuss

Detect tapping the android back button to close the keyboard in flutter

I am searching for a possibility to detect when the user taps the android back button on the bottom in order to close the keyboard in flutter. The problem is the following: If the user taps a text field, it gets the focus and the keyboard appears, everything is fine here. I put the text field inside a GestureDetector so if the user taps somewhere outside the text field, unfocus() is called. But on android there is another way to close the keyboard: Using the back button from the smartphone on the bottom. Is there any way to detect when the user taps it while the keyboard was open? As I understand, WillPopScope only works when the back button points to the left, but when the keyboard is opened, the back button points to the bottom and it has another purpose. The keyboard_visibility package did not work for me. When adding a listener to the KeyboardVisibilityNotification, the methods onHide and onChanged did not fire.

Answer

Since the keyboard_visibility package is no longer updated, you can use this new one: Flutter Keyboard Visibility. It uses null safety and is getting updates.

Here is my approach, using the FocusManager instead of the FocusScope.

late final KeyboardVisibilityController _keyboardVisibilityController;
late StreamSubscription<bool> keyboardSubscription;

  @override
  void initState() {
    super.initState();
    _keyboardVisibilityController = KeyboardVisibilityController();
    keyboardSubscription = _keyboardVisibilityController.onChange.listen((isVisible) {
      if (!isVisible) FocusManager.instance.primaryFocus?.unfocus();
    });
  }

  @override
  void dispose() {
    keyboardSubscription.cancel();
    super.dispose();
  }

See the package for alternative implementations.

Source: stackoverflow
Text is available under the Creative Commons Attribution-ShareAlike License; additional terms may apply. By using this site, you agree to the Privacy Policy, and Copyright Policy. Content is available under CC BY-SA 3.0 unless otherwise noted. The answers/resolutions are collected from stackoverflow, are licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0 © No Copyrights, All Questions are retrived from public domain..