Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to access context in repository [MVVM]

I am developing an Android application that makes use of the MVVM architecture. My problem is that my repository (that is responsible for fetching JSON from the web) needs access to a context.

I've read several suggestions on StackOverflow. So far the most reasonable options I've gathered are the following:

  • Use Dagger 2 to somehow inject the context.

  • Let my ViewModel extend from AndroidViewModel to get the application context and pass that to the repo.

As of right now I have one ViewModel and one Repo

RoomFragmentViewModel.java:

public class MyViewModel extends ViewModel {
    private MutableLiveData<List<JSONObject>> rooms;
    private Repository repository;

    public void init(){
        if(rooms != null){
            return;
        }
        repository = repository.getInstance();
        rooms = repository.getRooms();
    }

Repository.java:

public class Repository {

    private static Repository instance;
    private ArrayList<JSONObject> actualRooms = new ArrayList<>();


    public static Repository getInstance() {
        if (instance == null) {
            instance = new Repository();
        }
        return instance;
    }

   
    public MutableLiveData<List<JSONObject>> getRooms() {
        ...
    }

    private void setRooms() {
        ...
        // Here I am fetching data from my server, but in order to to do so I require a context

        String url = "http://10.0.0.5:8000/api";

        JsonObjectRequest jsonObjectRequest = new JsonObjectRequest
                (Request.Method.GET, null, new Response.Listener<JSONObject>() {...

        // Context needs to be provided right here:
        MySingleton.getInstance(context).addToRequestQueue(jsonObjectRequest);

    }
}

Due to contradictory statements on the Internet I am unsure how I should resolve this problem. If your answer makes use of dagger could you be so nice to provide an explanation with code since I am completely new to dagger. Thank you in advance.

like image 533
Josip Domazet Avatar asked Aug 17 '19 19:08

Josip Domazet


2 Answers

I ended up injecting the context via dagger. However, from my point of view making your ViewModel extend from AndroidViewModel is also an valid option and definitely the easier one. If I were developing an simple and small application I would probably recommend just extending from AndroidViewModel to avoid unnecessary boilerplate code from dagger.

I followed the dagger series from codingwithmith in order to implement my own solution. So his channel might be useful for future readers: https://www.youtube.com/channel/UCoNZZLhPuuRteu02rh7bzsw/featured

like image 63
Josip Domazet Avatar answered Oct 23 '22 23:10

Josip Domazet


Using Android Hilt

//Dagger - Hilt
def hilt_version = "2.31.2-alpha"
implementation "com.google.dagger:hilt-android:$hilt_version"
kapt "com.google.dagger:hilt-android-compiler:$hilt_version"

def hilt_viewmodel_version = "1.0.0-alpha03"
implementation "androidx.hilt:hilt-lifecycle-viewmodel:$hilt_viewmodel_version"
kapt "androidx.hilt:hilt-compiler:$hilt_viewmodel_version"

.

@Module
@InstallIn(SingletonComponent::class)
class AppModule {

    @Singleton
    @Provides
    fun provideContext(application: Application): Context = application.applicationContext
}

Then pass it via constructor

class MyRepository @Inject constructor(private val context: Context) {
...
}
like image 43
Thiago Avatar answered Oct 24 '22 00:10

Thiago