I have a fragment that launches a background thread to do some work and uses a handler callback to update some UI when the thread finishes its task.
public class CodeFragment extends Fragment implements View.OnClickListener, Handler.Callback {
private CodeDataViewModel codeDataViewModel;
private Handler uiHandler;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState){
View view = inflater.inflate(R.layout.fragment_code, container, false);
uiHandler = new Handler(Looper.getMainLooper(), this);
return view;
}
@Override
public boolean handleMessage(Message msg){
if(msg.what == 0){
BFResult result = (BFResult)msg.obj;
codeDataViewModel.setOutput(result);
runButton.setIcon(ResourcesCompat.getDrawable(requireActivity().getResources(), R.drawable.ic_baseline_play_arrow_24, null));
runButton.setText(getString(R.string.run));
codeDataViewModel.setShouldRun(true);
if(result.errorCode != BFErrorCodes.UserAbort){
ViewPager2 viewPager2 = getActivity().findViewById(R.id.view_pager);
viewPager2.setCurrentItem(1);
}
}
codeDataViewModel.setInterpreterThread(null);
return true;
}
The issue I have is when the screen rotates while the thread is still running, then, after the thread finishes executing and when handleMessage starts being executed I get the following exception in handleMessage at the line runButton.setIcon(...)
FATAL EXCEPTION: main
java.lang.IllegalStateException: Fragment CodeFragment{7f397b9} (ea45dd9d-5419-4d22-8f56-11c7fed9f3bd) not attached to an activity.
at androidx.fragment.app.Fragment.requireActivity(Fragment.java:928)
at com.sandeept.brainfkinterpreter.fragments.CodeFragment.handleMessage(CodeFragment.java:117)
Now, I know this is because the activity and the fragments are recreated when a configuration change occurs. And because the handleMessage function being executed is of the old fragment that is now no longer attached to the activity there is a run time error.
What I don't know is how to fix this. I thought about using setRetainInstance(true), but this has been deprecated since the introduction of view models. I don't know how view models are going to be helpful in this case.
So, how do I handle this issue?