Я только что написал это. В моем примере работает у меня, и я надеюсь, что это решение подойдет и вам, или даст вам лучшее представление о том, как это сделать.
Шаг 1. Добавьте класс MyApplication.
public class MyApplication extends Application {
private BaseActivity currentActivity;
@Override
public void onCreate() {
super.onCreate();
}
public BaseActivity getCurrentActivity() {
return currentActivity;
}
public void setCurrentActivity(BaseActivity currentActivity) {
this.currentActivity = currentActivity;
}
}
Step 2. В BaseActivity добавьте метод для сохранения currentActivity в классе MyApplication.
public void setCurrentActivity(BaseActivity activity) {
((MyApplication) getApplication()).setCurrentActivity(activity);
}
Шаг 3. Создайте класс ProgressBarHolder - он будет обрабатывать logi c для добавления индикатора выполнения в макет активности.
добавьте идентификатор к ресурсу, он понадобится позже, чтобы найти ссылку на индикатор выполнения при повороте экрана
<resources>
<item type="id" name="progress"/>
</resources>
теперь создайте класс ProgressBarHolder
public class ProgressBarHolder {
private ProgressBar mProgressBar;
public ProgressBarHolder(Context context) {
mProgressBar = new ProgressBar(context, null, android.R.attr.progressBarStyleLarge);
mProgressBar.setId(R.id.progress);
mProgressBar.setIndeterminate(true);
mProgressBar.setVisibility(View.GONE);
}
//ADD VIEW LOGIC IS IN SHOW BECAUSE WHEN WE ROTATE THE SCREEN NEW LAYOUT WOULD BE CREATED AND WE WOULDN'T HAVE REFERENCE TO PROGRESSBAR
public void show(Context context) {
ProgressBar progressBar = ((Activity) context).findViewById(R.id.progress);
if (progressBar == null) {
if (mProgressBar.getParent() != null)
((ViewGroup) mProgressBar.getParent()).removeView(mProgressBar);
RelativeLayout.LayoutParams params = new
RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT);
RelativeLayout layout = new RelativeLayout(context);
layout.setGravity(Gravity.CENTER);
layout.addView(mProgressBar);
((Activity) context).addContentView(layout, params);
}
mProgressBar.setVisibility(View.VISIBLE);
}
public void hide() {
mProgressBar.setVisibility(View.GONE);
}
}
Шаг 4. Замените ViewModel на AndroidViewModel - это важно, потому что AndroidViewModel имеет ссылку на приложение
public class MyViewModel extends AndroidViewModel {
private ProgressBarHolder progressBarHolder;
public MutableLiveData<String> data = new MutableLiveData<>(); //NOT IMPORTANT, JUST TO OBSERVE RESULT IN MAINACTIVITY
public MyViewModel(@NonNull Application application) {
super(application);
progressBarHolder = new ProgressBarHolder(((MyApplication) application).getCurrentActivity());
}
// EXAMPLE - WAIT 5 SECONDS TO GET RESULT
public void getData() {
//TIME TO SHOW PROGRESS
progressBarHolder.show(((MyApplication) getApplication()).getCurrentActivity());
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
data.setValue(String.valueOf((int) (Math.random() * 50 + 1)));
//HIDE IT WHEN TASK IS FINISHED
progressBarHolder.hide();
}
}, 5000);
}
}
Шаг 5. Добавьте MyViewModel в MainActivity и наблюдайте за результатом.
public class MainActivity extends BaseActivity {
private MyViewModel myViewModel;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setCurrentActivity(this);
final TextView textView = findViewById(R.id.result);
Button hitMe = findViewById(R.id.hit_me);
ViewModelProvider.Factory factory = ViewModelProvider.AndroidViewModelFactory.getInstance(getApplication());
myViewModel = new ViewModelProvider(this, factory).get(MyViewModel.class);
myViewModel.data.observe(this, new Observer<String>() {
@Override
public void onChanged(String result) {
textView.setText(result);
}
});
hitMe.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
myViewModel.getData();
}
});
}
}