JarsOfJam-Scheduler
JarsOfJam-Scheduler

Reputation: 3149

In a fragment, how to find a view defined in the activity's layout?

In my activity's layout, I have a view which I'd want to access from its attached fragment.

How could I do it?

Normally, from a fragment, to find a view defined in a fragment's layout (so it's another use case), I just use the inflater to inflate the fragment's layout, and call findVieById.

But since my view is defined in the activity's layout, I can't do this.

Could I use getActivity().findViewById?

Upvotes: 0

Views: 86

Answers (3)

EpicPandaForce
EpicPandaForce

Reputation: 81539

In my activity's layout, I have a view which I'd want to access from its attached fragment.

No, you don't want to.

How could I do it?

getActivity().findViewById(R.id.blah), but you shouldn't.

But since my view is defined in the activity's layout, I can't do this.

Technically you can, you just shouldn't.

Could I use getActivity().findViewById?

Yes, but you shouldn't.


As for the correct answer, this is why they created Android Architecture Components: ViewModel / LiveData - so that you wouldn't be tempted to access views directly. You could modify the data/state shared via ViewModel in one place, and thanks to LiveData all observers would be updated with it.

Therefore you never have to touch views directly, you just need to update data.

public class MyActivity extends AppCompatActivity {
    private MyViewModel myViewModel;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        myViewModel = ViewModelProviders.of(this).get(MyViewModel.class);

        myViewModel.myData().observe(this, (data) -> {
            if(data == null) return;

            updateViews(data);
        });
    }
}

and

public class MyViewModel extends ViewModel {
    public MyViewModel() {}

    private MutableLiveData<MyData> mutableData = new MutableLiveData<>();

    public LiveData<MyData> myData() {
        return mutableData;
    }

    public void updateData(MyData newData) {
        mutableData.postValue(newData);
    }
}

and

public class MyFragment extends Fragment {
    private MyViewModel myViewModel;

    @Override
    protected void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        myViewModel = ViewModelProviders.of(getActivity()).get(MyViewModel.class);

        myViewModel.myData().observe(getViewLifecycleOwner(), (data) -> {
            if(data == null) return;

            updateViews(data);
        });
    }
}

This way:

You can also find this technique in the official guides here.

Upvotes: 1

Harvey
Harvey

Reputation: 1375

It's not a good practice. You shouldn't do that. The Activity should handle its view on it own and you can trigger that handle function using an interface. Check this out.

https://developer.android.com/training/basics/fragments/communicating

Upvotes: 1

Suraj Vaishnav
Suraj Vaishnav

Reputation: 8305

Do this:

((YourActivityName)getActivity()).findViewById

or you can do findViewById for a view and make it global in your activity and can access it like:

((YourActivityName)getActivity()).viewName

Upvotes: 0

Related Questions