Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MVVM in android,accessing assetManager without breaking the pattern

I have a JSON file in the assets folder and DataManager(repository) class needs it so assetManager(and context) should have access to the assets.

The problem is that based on Best practice, Android context or android specific code should not be passed into the data layer(ViewModel-Repo-Model) because of writing unit tests or etc easily and also view should not interact with the data layer directly.

I ended up providing the list using and injecting it to the repository.

Is this the right thing to do?

-Thanks

P.S: my Module class which provides the list

@Module
public class UtilModule {

    @Provides
    @JsonScope
    JsonUtil provideJsonUtil(AssetManager assetManager){
        return new JsonUtil(assetManager);
    }

    @Provides
    @JsonScope
    String provideJson(JsonUtil util){
        return util.getJson();
    }

    @Provides
    @JsonScope
    Type provideType(){
        return new TypeToken<List<Data>>() {}.getType();
    }
    @Provides
    @JsonScope
    DataManager provideDataManager (Gson gson, Type type,String json) {
        return new DataManager (gson.fromJson(json, type));
    }
}
like image 679
Hessam-Emami Avatar asked Feb 03 '19 13:02

Hessam-Emami


1 Answers

It's not a violation of MVVM for a ViewModel and/or Repository to access the Application context directly, which is all you need to access the AssetsManager. Calling Application.getAssets() is OK because the ViewModel doesn't use any particular Activity's context.

For example, you can use the Google-provided AndroidViewModel subclass instead of the superclass ViewModel. AndroidViewModel takes an Application in its constructor (ViewModelProviders will inject it for you). You could pass your Application to your Repository in its constructor.

Alternately, you could use Dagger dependency injection to inject an Application directly into your Repository. (Injecting the Application context is a bit tricky. See Dagger 2 injecting Android Context and this issue filed on the Danger github repo.) If you want to make it really slick, you could configure a provider for AssetManager and inject it directly into your Repository.

Finally, if you are using Room, and all you want is to pre-populate your Room database with a pre-configured database stored in assets, you can follow instructions here: How to use Room Persistence Library with pre-populated database?

like image 93
Dan Fabulich Avatar answered Sep 19 '22 21:09

Dan Fabulich