Skip to content

Snappy1

  • Home
  • Android
  • What
  • How
  • Is
  • Can
  • Does
  • Do
  • Why
  • Are
  • Who
  • Toggle search form

[FIXED] android – How can i inject my Retrofit DataService using Dagger2

Posted on November 11, 2022 By

Solution 1 :

I’ll assume you want to keep your RetrofitInstance singleton available for now, at least until you have migrated all Retrofit uses to Dagger 2.

In order to inject an interface, or a class whose constructor you don’t control, you need to use a Module. This tells Dagger how to create instances of that class or interface given some dependencies:

@Module
public class WebServiceModule {
    @Singleton
    @Provides
    Retrofit provideRetrofit() {
        // This method tells Dagger all it needs to know about creating
        // a Retrofit instance. This will be replaced by something closer
        // to BWappsandmore's answer after RetrofitInstance is no longer needed.
        return RetrofitInstance.getRetrofitInstance();
    }

    @Singleton
    @Provides
    GetNoticeDataService provideGetNoticeDataService(Retrofit retrofit) {
        return retrofit.create(GetNoticeDataService.class);
    }

This module can then be included in your Component, which will in turn create any objects it knows how to create, either from modules, @BindsInstance values passed into your component factory method, or classes with @Inject constructors. Since you control your interactor’s constructor, you can simply annotate it with @Inject:

// @Reusable or @Singleton if you only need one interactor of this type.
public class GetNoticeInteractorImpl implements MainContract.GetNoticeInteractor {
    private GetNoticeDataService service

    @Inject
    GetNoticeInteractorImpl(GetNoticeDataService service) {
        this.service = service;
    }

    private LatLng getloc(){
        return currentLocation;
    }
    @SuppressLint("CheckResult")
    @Override
    public void getNoticeArrayList(final OnFinishedListener onFinishedListener) {

        // Our service was injected in the constructor, so there
        // is no need to create it here.

        // You might also consider injecting your schedulers in the future
        // for unit testing.
        if(currentLocation!=null) {
            service.getNoticeData(getloc().latitude, getloc().longitude)
                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                            .subscribe(items -> onFinishedListener.onFinished(items.getNoticeArrayList(), items.getMain(), items.getWind()), onFinishedListener::onFailure);

        }
    }

}

@Module
abstract class AnotherModule { // or interface
    @Binds
    abstract MainContract.GetNoticeInteractor bindGetNoticeInteractor(GetNoticeInteractorImpl implementation);
}

Of course, this is useless if you can’t ultimately access your interactor. Since you don’t even create your Activity classes, you need to request injection from a Component. In Android apps, this is typically created within the Application object in onCreate().

@Component(modules = {WebServicesModule.class, AnotherModule.class})
@Singleton
public interface AppComponent {
    @Component.Factory
    interface Factory {
        AppComponent create(@BindsInstance Application application); // or whatever
    }

    void bindMainActivity(MainActivity activity);
}

// Probably not a singleton, but if you create an activity scope later, this might use that scope.
class MainPresenter {
    @Inject
    public MainPresenter(MainContract.GetNoticeInteractor interactor) {
        this.getNoticeInteractor = interactor
    }
    // ...
}

class MainActivity {
    @Inject
    MainPresenter presenter;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        somehowGetComponent().inject(this);
        super(savedInstanceState);
        // ...
    }
    // ...
}

Now, since your MainActivity requires a MainPresenter, Dagger will create one for you when you request injection. This in turn requires a GetNoticeInteractor, which requires GetNoticeInteractorImpl, and so forth, and Dagger will take care of all of this behind the scenes.

READ  [FIXED] android - How to set unfixed height for elements in Scaffold
Powered by Inline Related Posts

If your presenter’s constructor requires other arguments (such as a View), it might be simpler for now for MainActivity to request injection directly into the presenter. Ultimately, you will want all of your inject(SomeClass target) methods to refer to Activities, Services, and such, since there is no other way to inject those until your minSdkVersion is 28 or higher.

Solution 2 :

@Module
object WebServiceModule {

    @Singleton
    @Provides
    fun providesGetNoticeDataService(retrofit: Retrofit): GetNoticeDataService =
        retrofit.create<GetNoticeDataService>(GetNoticeDataService::class.java)

    @Provides
    fun providesGsonConverterFactory(): GsonConverterFactory = GsonConverterFactory.create()

    @Provides
    fun providesOkHttpClient(loggingInterceptor: HttpLoggingInterceptor): OkHttpClient =
        OkHttpClient.Builder()
            .connectTimeout(20, TimeUnit.SECONDS)
            .readTimeout(20, TimeUnit.SECONDS)
            .addInterceptor(loggingInterceptor)
            .build()

    @Provides
    fun providesOkHttpLoggingInterceptor(): HttpLoggingInterceptor =
        HttpLoggingInterceptor().apply {
            level = HttpLoggingInterceptor.Level.BODY
        }

    @Provides
    fun provideRxJava2CallAdapterFactory(): RxJava2CallAdapterFactory =
        RxJava2CallAdapterFactory.create()

    @Provides
    fun providesRetrofit(
        client: OkHttpClient,
        converterFactory: GsonConverterFactory,
        adapterFactory: RxJava2CallAdapterFactory
    ): Retrofit = Retrofit.Builder()        
        .baseUrl(BASE_URL) 
        .addConverterFactory(converterFactory)
        .addCallAdapterFactory(adapterFactory)
        .client(client)
        .build()
}

Problem :

In my MVP architecture i have Retrofit Instance

public class RetrofitInstance {
    private static Retrofit retrofit;
    private static final String BASE_URL = "http://api.openweathermap.org/data/2.5/";

    /**
     * Create an instance of Retrofit object
     * */
    public static Retrofit getRetrofitInstance() {
        if (retrofit == null) {
            retrofit = new retrofit2.Retrofit.Builder()
                    .baseUrl(BASE_URL)
                    .addConverterFactory(GsonConverterFactory.create())
                    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                    .build();
        }
        return retrofit;
    }
}

And DataService for it

public interface GetNoticeDataService {
    @GET("weather?appid=0194877ecdcac230396a119c01d46100")
    Observable<NoticeList> getNoticeData(@Query("lat") double lat , @Query("lon") double lon );
}

Also i have DataInteractor which is using RxJava Observable service to call api

public class GetNoticeIntractorImpl implements MainContract.GetNoticeIntractor {
    private LatLng getloc(){
        return currentLocation;
    }
    @SuppressLint("CheckResult")
    @Override
    public void getNoticeArrayList(final OnFinishedListener onFinishedListener) {

        /** Create handle for the RetrofitInstance interface*/
        GetNoticeDataService service = RetrofitInstance.getRetrofitInstance().create(GetNoticeDataService.class);
        /** Using RxJava Observable response to handle retrofit api*/
        if(currentLocation!=null) {
            service.getNoticeData(getloc().latitude, getloc().longitude)
                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                            .subscribe(items -> onFinishedListener.onFinished(items.getNoticeArrayList(), items.getMain(), items.getWind()), onFinishedListener::onFailure);

        }
    }

}

Here is presenter

public class MainPresenterImpl implements MainContract.presenter, MainContract.GetNoticeIntractor.OnFinishedListener {
 private MainContract.MainView mainView;
        private MainContract.GetNoticeIntractor getNoticeIntractor;
        @Inject
        public MainPresenterImpl(MainContract.MainView mainView, MainContract.GetNoticeIntractor getNoticeIntractor) {
            this.mainView = mainView;
            this.getNoticeIntractor = getNoticeIntractor;
        }

        @Override
        public void onDestroy() {

            mainView = null;

        }

        @Override
        public void onRefreshButtonClick() {

            if(mainView != null){
                mainView.showProgress();
            }
            getNoticeIntractor.getNoticeArrayList(this);
        }

        @Override
        public void requestDataFromServer() {
            getNoticeIntractor.getNoticeArrayList(this);
        }


        @Override
        public void onFinished(ArrayList<Notice> noticeArrayList, Main main, Wind wind) {
            if(mainView != null){
                mainView.setDataToRecyclerView(noticeArrayList,main,wind);
                mainView.hideProgress();
            }
        }



        @Override
        public void onFailure(Throwable t) {
            if(mainView != null){
                mainView.onResponseFailure(t);
                mainView.hideProgress();
            }
        }
    }

And MainContract

public interface MainContract {
    /**
     * Call when user interact with the view and other when view OnDestroy()
     * */
    interface presenter{

        void onDestroy();

        void onRefreshButtonClick();

        void requestDataFromServer();

    }

    /**
     * showProgress() and hideProgress() would be used for displaying and hiding the progressBar
     * while the setDataToRecyclerView and onResponseFailure is fetched from the GetNoticeInteractorImpl class
     **/
    interface MainView {

        void showProgress();

        void hideProgress();

        void setDataToRecyclerView(ArrayList<Notice> noticeArrayList, Main main, Wind wind);

        void onResponseFailure(Throwable throwable);

    }

    /**
     * Intractors are classes built for fetching data from your database, web services, or any other data source.
     **/
    interface GetNoticeIntractor {

        interface OnFinishedListener {
            void onFinished(ArrayList<Notice> noticeArrayList, Main main, Wind wind);
            void onFailure(Throwable t);
        }
        void getNoticeArrayList(OnFinishedListener onFinishedListener);

    }
}

Adapter for MyActivity

public class NoticeAdapter extends RecyclerView.Adapter<NoticeAdapter.EmployeeViewHolder> {

    private static Wind wind;
    private static ArrayList<Notice> dataList;
    private static Main main;
    private Date currentTime = Calendar.getInstance().getTime();
    public static String date;
    private Context mContext;

    private RecyclerItemClickListener recyclerItemClickListener;
    public NoticeAdapter(ArrayList<Notice> dataList, Main main, Wind wind, RecyclerItemClickListener recyclerItemClickListener,Context context) {
        NoticeAdapter.dataList = dataList;
        NoticeAdapter.main = main;
        NoticeAdapter.wind = wind;
        this.recyclerItemClickListener = recyclerItemClickListener;
        this.mContext=context;
    }

    @NonNull
    @Override
    public EmployeeViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
        View view = layoutInflater.inflate(R.layout.single_view_row, parent, false);
        return new EmployeeViewHolder(view);
    }

    @SuppressLint("SetTextI18n")
    @Override
    public void onBindViewHolder(@NonNull EmployeeViewHolder holder, @SuppressLint("RecyclerView") final int position) {
        setDate(currentTime.toString().substring(0,currentTime.toString().length()-18));
        if(getAddressMap()!=null){holder.txtNoticeAddress.setText("Loc: "+getAddressMap());}else{holder.txtNoticeAddress.setText("Loc: Unknown location");}
        holder.imageIcon.setImageURI(Uri.parse("android.resource://com.locweather/drawable/i"+dataList.get(position).getIcon()));
        holder.txtNoticeWind.setText("Wind: "+roundUp(+wind.getSpeed())+"m/s, "+arrow());
        holder.txtNoticeTempMain.setText(roundUp(+main.getTemp())+"°C");
        holder.txtNoticeWeather.setText(dataList.get(position).getWeather()+" : "+dataList.get(position).getInfo());
        holder.txtNoticeTemp.setText("Feels: "+roundUp(+main.getFeelsLike())+"°C ");
        holder.txtNoticeTime.setText(date);
        holder.txtNoticeHumidity.setText("Humidity: "+main.getHumidity()+"%");
        holder.txtNoticePressure.setText("Pressure: "+main.getPressure()+"hPa");
        holder.itemView.setOnClickListener(v -> {
            recyclerItemClickListener.onItemClick();
            saveNoticeList(mContext,dataList); });
        holder.saveButton.setOnClickListener(v -> {
            recyclerItemClickListener.onItemClick();
            saveNoticeList(mContext,dataList); });
    }

    private static String getAddressMap() {
        return MapsActivity.addressMap;
    }

    private static void setDate(String date) {
        NoticeAdapter.date = date;
    }

    @Override
    public int getItemCount() {
        return dataList.size();
    }
    private static LatLng getloc(){
        return currentLocation;
    }

    class EmployeeViewHolder extends RecyclerView.ViewHolder {
        ImageView imageIcon;
        Button saveButton;
        TextView txtNoticeWeather, txtNoticeTempMain,txtNoticeTemp, txtNoticeHumidity,txtNoticeAddress,txtNoticePressure,txtNoticeWind,txtNoticeTime;

        EmployeeViewHolder(View itemView) {
            super(itemView);
            saveButton=itemView.findViewById(R.id.save_button);
            imageIcon=itemView.findViewById(R.id.image_icon);
            txtNoticeTime= itemView.findViewById(R.id.txt_time);
            txtNoticeWind= itemView.findViewById(R.id.txt_notice_wind);
            txtNoticeAddress=  itemView.findViewById(R.id.txt_notice_title);
            txtNoticeWeather =  itemView.findViewById(R.id.txt_notice_weather);
            txtNoticeTemp =  itemView.findViewById(R.id.txt_notice_temp);
            txtNoticeHumidity =  itemView.findViewById(R.id.txt_notice_humidity);
            txtNoticePressure =  itemView.findViewById(R.id.txt_notice_pressure);
            txtNoticeTempMain =  itemView.findViewById(R.id.txt_notice_temp_main);
        }
    }
    private static void saveNoticeList(Context context, List<Notice> noticeList) {
        if (context != null && noticeList != null) {
            WeatherData weatherData = new WeatherData(getAddressMap(), wind.getSpeed(), wind.getDeg(), dataList.get(0).getIcon(), dataList.get(0).getInfo(), dataList.get(0).getWeather(), main.getTemp(), main.getFeelsLike(), main.getHumidity(), main.getPressure(), date, getloc().latitude, getloc().longitude);
            WeatherDatabase.getInstance(context)
                    .weatherDao()
                    .save(weatherData);
        }
    }

How can i inject this DataService to my Interactor by using Dagger2? Should i use Singleton or Component or something else?
I’ll be glad of any kind of help.

READ  [FIXED] android - wifiManager.startScan() returns false
Powered by Inline Related Posts

Comments

Comment posted by sippinman

Yes, im using recyclerview and it adapter for activity, i can add presenter and adapter for better understnding

Comment posted by github.com/evgenyuliganets/LocWeather

Already add, check pls and edit for my situation deeply if u can,

Comment posted by sippinman

what is .inject(this) and where it declared?

Comment posted by sippinman

is it kotlin? i need solution for java

Comment posted by BWappsAndmore

@sippinman it is in Kotlin, but I think it it easy to either convert it to Java or include it in your project as it is – Android Studio makes it possible.

Comment posted by sippinman

can you please convert it and add it here? because i’ve never use kotlin and i cant decompile it in my project.

Android Tags:android, dagger-2, dependency-injection, retrofit, rx-java

Post navigation

Previous Post: Can a beginner learn Moonlight Sonata 1st Movement?
Next Post: [FIXED] java – App keeps crashing when ListView item is clicked on

Related Posts

[FIXED] How to run code inspection on an entire project in Android Studio Android
[FIXED] android – JPEG Taking up ~20x Space as Expected Android
[FIXED] java – android studio switch how to pro-grammatically set the state of the switch Android
[FIXED] java – How to open a specific activity from an external link clicking Android
[FIXED] android – 6: BuyFlow UI needs to be shown Android
[FIXED] android – Why is there a need for programatically creating views? Android

Archives

  • March 2023
  • February 2023
  • January 2023
  • December 2022
  • November 2022
  • October 2022
  • September 2022

Categories

  • ¿Cómo
  • ¿Cuál
  • ¿Cuándo
  • ¿Cuántas
  • ¿Cuánto
  • ¿Qué
  • Android
  • Are
  • At
  • C'est
  • Can
  • Comment
  • Did
  • Do
  • Does
  • Est-ce
  • Est-il
  • For
  • Has
  • Hat
  • How
  • In
  • Is
  • Ist
  • Kann
  • Où
  • Pourquoi
  • Quand
  • Quel
  • Quelle
  • Quelles
  • Quels
  • Qui
  • Should
  • Sind
  • Sollte
  • Uncategorized
  • Wann
  • Warum
  • Was
  • Welche
  • Welchen
  • Welcher
  • Welches
  • Were
  • What
  • What's
  • When
  • Where
  • Which
  • Who
  • Who's
  • Why
  • Wie
  • Will
  • Wird
  • Wo
  • Woher
  • you can create a selvedge edge: You can make the edges of garter stitch more smooth by slipping the first stitch of every row.2022-02-04
  • you really only need to know two patterns: garter stitch

Recent Posts

  • Which is stronger 19 gauge or 23 gauge?
  • Does BMW still use GM transmissions?
  • Is primary or secondary market research better?
  • What does it mean when ADT says low battery?
  • Can a baby sleep on a regular mattress?

Recent Comments

No comments to show.

Copyright © 2023 Snappy1.

Powered by PressBook Grid Dark theme