Search code examples
androidandroid-studioandroid-intentsplash-screenandroid-livedata

Cannot go to MainActivity when using LiveData


I have splash screen without a layout file. This is what I have tried:

 public class SplashActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        if (!isNotAuthenticated()) {
            openLoginInActivity();
        } else {
            openMainActivity();
        }

        finish();
    }

    private void openMainActivity() {
        viewModel.idLiveData.observe(this, new Observer<String>() {
            @Override
            public void onChanged(String id) {
                Intent intent = new Intent(SplashActivity.this, MainActivity.class);
                intent.putExtra("id", id);
                startActivity(intent); //Go to MainActivity
            }
        });
    }
}

Using this code, I get this error:

2019-09-03 12:03:06.615 1871-1934/? E/ViewRootImpl[myapp]: Could not unlock surface
java.lang.IllegalArgumentException
    at android.view.Surface.nativeUnlockCanvasAndPost(Native Method)
    at android.view.Surface.unlockSwCanvasAndPost(Surface.java:382)
    at android.view.Surface.unlockCanvasAndPost(Surface.java:363)
    at android.view.ViewRootImpl.drawSoftware(ViewRootImpl.java:3451)
    at android.view.ViewRootImpl.draw(ViewRootImpl.java:3339)

If i get the creation if the intent outside onChanged(), everything works fine. I have added a log statement and onChanged is not even triggered. So how can I move to the next activity without that error?

Edit:

public class SplashViewModel extends ViewModel {
    private SplashRepository splashRepository;
    MutableLiveData<String> idLiveData;

    @Inject
    SplashViewModel(SplashRepository splashRepository) {
        this.splashRepository = splashRepository;
        idLiveData = splashRepository.addIdToLiveData();
    }
}

Solution

  • How I used live data in Splash Activity

    class SplashActivity : BaseActivity<ActivitySplashBinding, SplashViewModel>() {
    override val mViewModel: SplashViewModel by currentScope.inject()
    
    override fun getLayoutResId(): Int {
        return R.layout.activity_splash
    }
    
    override fun initialization() {
    
    }
    
    override fun initializeObserver() {
        mViewModel.liveData.observe(this, Observer {
            if (it) {
                launchActivityWithFinish<LoginActivity>()
            }
        })
    }}
    

    Here is My SplashViewModel

    class SplashViewModel : BaseViewModel() {
    val liveData = MutableLiveData<Boolean>()
    
    init {
        viewModelScope.launch {
            delay(SPLASH_TIME_OUT)
            liveData.postValue(true)
        }
    }}
    

    My SplashActivity In java

    public class SplashActivity1 extends BaseActivity<ActivitySplashBinding, SplashViewModel> {
    @NotNull
    @Override
    protected SplashViewModel getMViewModel() {
        return new SplashViewModel();
    }
    
    @Override
    public int getLayoutResId() {
        return R.layout.activity_splash;
    }
    
    @Override
    public void initialization() {
    
    }
    
    @Override
    public void initializeObserver() {
        getMViewModel().getLiveData().observe(this, aBoolean -> {
            if (aBoolean) {
                Intent intent = new Intent(SplashActivity1.this, MainActivity.class);
                intent.putExtra("id", "id");
                startActivity(intent); //Go to MainActivity
                finish();
            }
        });
    }}
    

    My SplashViewModel In Java

    public class SplashViewModel extends BaseViewModel {
    
    public MutableLiveData<Boolean> liveData = new MutableLiveData<>(false);
    
    public SplashViewModel(){
        new Handler().postDelayed(() -> liveData.postValue(true),SPLASH_TIME_OUT);
    }}
    

    It perfectly works for me in Kotlin & Java both