Skip to content

Instantly share code, notes, and snippets.

@bhaskar253
Last active May 7, 2025 21:54
Show Gist options
  • Save bhaskar253/7b93b06aea6e580ab6482a847e11f092 to your computer and use it in GitHub Desktop.
Save bhaskar253/7b93b06aea6e580ab6482a847e11f092 to your computer and use it in GitHub Desktop.
Random Experiment
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<ProgressBar
android:id="@+id/progressBar"
android:layout_width="40dp"
android:layout_height="40dp"
android:visibility="gone"
tools:visibility="visible"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.MyApp"
tools:targetApi="31">
<activity
android:name=".SecondActivity"
android:excludeFromRecents="true"
android:launchMode="singleTask"
android:configChanges="orientation|screenSize|screenLayout|keyboardHidden|navigation|mnc|mcc"
android:theme="@style/Theme.AppCompat.Dialog"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="example"
android:host="gizmos" />
</intent-filter>
</activity>
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
package com.example.myapp
import android.os.Bundle
import android.view.View
import android.widget.ProgressBar
import android.widget.TextView
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.lifecycleScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
class MainActivity : AppCompatActivity() {
private lateinit var currentState: State
private val _myLiveData = MutableLiveData<State>(State.Idle)
private val myLiveData: LiveData<State>
get() = _myLiveData
private lateinit var progressBar: ProgressBar
private lateinit var textView: TextView
private var dialog: AlertDialog? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContentView(R.layout.activity_main)
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
progressBar = findViewById(R.id.progressBar)
textView = findViewById(R.id.textView)
textView.setOnClickListener {
if (textView.text == "Hello World!") {
startStateMachine()
} else {
textView.text = "Hello World!"
}
}
insets
}
observeData()
}
private fun observeData() {
myLiveData.observe(this) {
when (it) {
is State.Loading -> {
if (::progressBar.isInitialized && ::textView.isInitialized) {
progressBar.visibility = View.VISIBLE
textView.visibility = View.GONE
}
}
is State.Error -> {
if (::progressBar.isInitialized && ::textView.isInitialized) {
progressBar.visibility = View.GONE
textView.text = it.error
textView.visibility = View.VISIBLE
}
}
is State.LaunchDialog1 -> {
if (::progressBar.isInitialized && ::textView.isInitialized) {
progressBar.visibility = View.GONE
// textView.text = "Launch Dialog 1"
dialog = AlertDialog.Builder(this).apply {
title = "Dialog 1"
setMessage("This is Dialog 1")
setPositiveButton("OK") {_, _ ->
currentState = State.Idle
_myLiveData.postValue(currentState)
}
}.create()
dialog?.show()
}
}
is State.LaunchDialog2 -> {
if (::progressBar.isInitialized && ::textView.isInitialized) {
progressBar.visibility = View.GONE
// textView.text = "Launch Dialog 2"
dialog = AlertDialog.Builder(this).apply {
title = "Dialog 2"
setMessage("This is Dialog 2")
setPositiveButton("OK") {_, _ ->
currentState = State.Idle
_myLiveData.postValue(currentState)
}
}.create()
dialog?.show()
}
}
is State.LaunchDialog3 -> {
if (::progressBar.isInitialized && ::textView.isInitialized) {
progressBar.visibility = View.GONE
// textView.text = "Launch Dialog 3"
dialog = AlertDialog.Builder(this).apply {
title = "Dialog 3"
setMessage("This is Dialog 3")
setPositiveButton("OK") {_, _ ->
currentState = State.Idle
_myLiveData.postValue(currentState)
}
}.create()
dialog?.show()
}
}
else -> {
if (::progressBar.isInitialized && ::textView.isInitialized) {
progressBar.visibility = View.GONE
// textView.text = "Hello World!"
textView.visibility = View.VISIBLE
}
}
}
}
}
private fun startStateMachine() {
lifecycleScope.launch(Dispatchers.IO) {
currentState = State.Idle
delay(200L)
currentState = State.Loading
_myLiveData.postValue(currentState)
delay(10000L)
when ((1..4).random()) {
1 -> currentState = State.Error("random error")
2 -> currentState = State.LaunchDialog1
3 -> currentState = State.LaunchDialog2
4 -> currentState = State.LaunchDialog3
}
_myLiveData.postValue(currentState)
}
}
}
sealed class State {
data object Loading : State()
data class Error(val error: String) : State()
data object LaunchDialog1 : State()
data object LaunchDialog2 : State()
data object LaunchDialog3 : State()
data object Idle : State()
}
package com.example.myapp
import android.app.Dialog
import android.content.Context
import android.content.DialogInterface
import android.content.Intent
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import androidx.activity.enableEdgeToEdge
import androidx.activity.viewModels
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.fragment.app.DialogFragment
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.fragment.app.viewModels
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
class SecondActivity : AppCompatActivity() {
private lateinit var dialogFragment: MyDialogFragment
private val viewModel: MyDialogViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContentView(R.layout.activity_second)
Log.d(TAG, "onCreate")
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
insets
}
if (savedInstanceState == null) {
dialogFragment = MyDialogFragment()
supportFragmentManager.beginTransaction()
.add(dialogFragment, "myDialog")
.commit()
} else {
dialogFragment = supportFragmentManager.findFragmentByTag("myDialog") as MyDialogFragment
}
}
override fun onDestroy() {
super.onDestroy()
Log.d(TAG, "onDestroy")
}
companion object {
const val TAG = "SecondActivity"
}
}
class MyDialogFragment() : DialogFragment() {
private val viewModel: MyDialogViewModel by activityViewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
//retainInstance = true
Log.d(TAG, "onCreate")
}
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
Log.d(TAG, "onCreateDialog")
val view = LayoutInflater.from(requireContext()).inflate(R.layout.custom_dialog, null)
viewModel.isDataReady.observe(this) {
Log.d(TAG, "onCreateDialog: isDataReady $it")
(dialog as? AlertDialog)?.setMessage("Actual Message - $it")
}
val builder = AlertDialog.Builder(requireContext(), com.google.android.material.R.style.ThemeOverlay_Material3_Dialog_Alert)
.setTitle("Sample Title")
.setMessage("Sample Message - ${viewModel.isDataReady.value}")
.setView(view)
.setPositiveButton("OK") { _, _ ->
dismiss()
}.setCancelable(false)
return builder.create()
}
override fun onDismiss(dialog: DialogInterface) {
super.onDismiss(dialog)
requireActivity().finish()
}
override fun onDestroyView() {
super.onDestroyView()
Log.d(TAG, "onDestroyView")
}
override fun onDestroy() {
super.onDestroy()
Log.d(TAG, "onDestroy")
}
override fun onDetach() {
super.onDetach()
Log.d(TAG, "onDetach")
}
override fun onAttach(context: Context) {
super.onAttach(context)
Log.d(TAG, "onAttach")
}
companion object {
const val TAG = "MyDialogFragment"
}
}
class MyDialogViewModel() : ViewModel() {
private val _isDataReady = MutableLiveData(false)
val isDataReady: LiveData<Boolean> = _isDataReady
init {
viewModelScope.launch {
delay(2000)
_isDataReady.postValue(true)
}
}
}
fun Context.startSecondActivity() {
val intent = Intent(this, SecondActivity::class.java).apply {
flags = Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS or Intent.FLAG_ACTIVITY_NEW_TASK
}
startActivity(intent)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment