简体   繁体   English

使用 Dagger 时在 Epoxy Controller 内实现 onClick 的最佳方法是什么

[英]What is the best way to implement onClick inside an Epoxy Controller when using Dagger

I am trying to implement Click functionality on an item inside a RecyclerView using airbnb.epoxy.我正在尝试使用 airbnb.epoxy 在RecyclerView内的项目上实现 Click 功能。 The problem is that i need context in order to navigate to another activity upon click.问题是我需要上下文才能在单击时导航到另一个活动。

What i have done: Following Epoxy's sample app I implemented an interface inside the EpoxyController that contains the function to be called when clicking an item in the recycler view.我做了什么:按照 Epoxy 的示例应用程序,我在 EpoxyController 中实现了一个接口,其中包含在单击回收器视图中的项目时要调用的函数。 I then make my main activity implement this interface and method, and instantiate the controller using its constructor inside the main activity and passing it a reference to the activity:然后我让我的主活动实现这个接口和方法,并在主活动中使用它的构造函数实例化控制器并将它传递给活动的引用:

    public class MortgageController extends TypedEpoxyController<List<Mortgage>> {

    private final MortgageCallBacks callBacks;

    public MortgageController(MortgageCallBacks callBacks) {
        this.callBacks = callBacks;
    }

    @Override
    protected void buildModels(List<Mortgage> mortgages) {
        Observable.from(mortgages)
                .subscribe(mortgage -> new MortgageModel_().id(mortgage.id())
                        .mortgage(mortgage)
                        .clicks(callBacks::onMortgageClicked)
                        .addTo(this));
    }


    public interface MortgageCallBacks {
        void onMortgageClicked(Mortgage mortgage);
    }
}

main activity's onCreate and onMortgageClick :主要活动的 onCreate 和onMortgageClick

 @Override
 protected void onCreate(Bundle savedInstanceState) {
     super.onCreate(savedInstanceState);

     controller = new MortgageController(this);
     initRecycler();
     controller.setData(mortgages);}
 
 @Override
 public void onMortgageClicked(Mortgage mortgage) {
     DetailActivity.start(this, mortgage);
 }

what i want to do while the above work, i am using Dagger2 in my project and would like to inject the controller into the MainActivity , injecting it is not the problem rather supplying the activity context, after a little bit of research i found epoxy allow activity injection, so i thought i could inject the main activity to the controller, but i am not sure this is the best way to go, and couldn't find example projects that implement this.在上述工作中我想做什么,我在我的项目中使用Dagger2并想将控制器注入MainActivity ,注入它不是问题,而是提供活动上下文,经过一些研究,我发现环氧树脂允许活动注入,所以我想我可以将主要活动注入控制器,但我不确定这是最好的方法,也找不到实现这一点的示例项目。

please enlighten me in what is the best way to do this请教我什么是最好的方法

It is not really relevant to this topic but I have just figure out how to navigate from one activity to another from an Epoxy Controller.它与本主题并不真正相关,但我刚刚弄清楚如何从一个活动从 Epoxy Controller 导航到另一个活动。

Let's say we need to implement the onSelected() .假设我们需要实现onSelected()

To moving between activities, we need an intent .But it requires a Context for the constructor.为了在活动之间移动,我们需要一个intent 。但它需要一个构造函数的Context Unfortunately, we can't achieve that in Epoxy Controller.不幸的是,我们无法在 Epoxy Controller 中实现这一点。 As a result, we need to implement the onSelected listener on an Activity or a Fragment , then pass it back to the Epoxy Controller.因此,我们需要在ActivityFragment上实现onSelected侦听器,然后将其传递回 Epoxy Controller。

Below is my epoxy controller:下面是我的环氧树脂控制器:

class TaskController(private val listener: TaskSelectListener) : TypedEpoxyController<List<Task>>() {
    override fun buildModels(tasks: List<Task>?) {
        tasks?.forEach { task ->
            TaskBindingModel_()
                .id(task.id)
                .taskToShow(task)
                .listener { model, _, _, _ ->
                    listener.onSelected(model.taskToShow())
                }.addTo(this)
        }

    }

    interface TaskSelectListener {
        fun onSelected(suggestion: Task)
    }

}

It is just a simple controller one, just only two things to notify in here.这只是一个简单的控制器,这里只需要通知两件事。 First is the interface .首先是interface Another class which has context will inherit this Interface class and implement the onSelected method we desires.另一个有context类将继承这个接口类并实现我们想要的onSelected方法。

The other thing is to pass that interface class to the Controller as a callback.另一件事是将该接口类作为回调传递给控制器​​。

In my MainActivity file, I implement like this:在我的 MainActivity 文件中,我是这样实现的:

class MainActivity : AppCompatActivity(), TaskController.TaskSelectListener {
    // pass `this` MainActivity because it is a TaskSelectListener
    private val taskController : TaskController by lazy { TaskController(this) }

     override fun onSelected(task: Task) {
        val intent = Intent(this, TomatoActivity::class.java)
        startActivity(intent)
    }
}

After A lot of research, I found an answer.经过大量研究,我找到了答案。 It may help others so here it is.它可能会帮助其他人,所以就在这里。

*I'm assuming you already have the basic features of Dagger2 working (if not look at Google's user guide ) The latest dagger versions (above 2.10) introduced dagger.android and allow you to inject an activity directly with a few simple steps: 1.Create a module that has a method annotated with @ContributesAndroidInjector 2.Add module to app component 3.make App implement HasActivityInjector *我假设您已经具备 Dagger2 的基本功能(如果没有查看Google 的用户指南)最新的 dagger 版本(2.10 以上)引入了 dagger.android 并允许您通过几个简单的步骤直接注入活动:1 .创建一个带有@ContributesAndroidInjector注释的方法的模块 2.将模块添加到应用程序组件 3.使应用程序实现HasActivityInjector

1.You can create an ActivityBindingModule, that has a method annotated by @ContributesAndroidInjector this auto generates a Subcomponent that we would otherwise have to write ourselves. 1.你可以创建一个ActivityBindingModule,它有一个@ContributesAndroidInjector注释的方法,这个自动生成一个子组件,否则我们必须自己编写。 You can specify the modules this subComponent will have.您可以指定此子组件将具有的模块。

@Module public abstract class ActivityBindingModule { @Module 公共抽象类 ActivityBindingModule {

@PerActivity
@ContributesAndroidInjector(modules = MainActivityModule.class)
abstract MainActivity mainActivityInjector();

} }

2.add Module to your AppComponent: 2.将模块添加到您的 AppComponent:

@Component(modules = {AppModule.class, ActivityBindingModule.class})
@Singleton
public interface AppComponent{
...
} 

3.make app implement HasActivityInjector and override AndroidInjector activityInjector(): 3.使应用程序实现HasActivityInjector并覆盖AndroidInjector activityInjector():

public class App implements HasActivityInjector {
@Inject
DispatchingAndroidInjector<Activity> activityInjector;

@Override
public void onCreate() {
    super.onCreate();
     ...
}

@Override
public AndroidInjector<Activity> activityInjector() {
    return dispatchingActivityInjector;
}

} }

Another way is to extend DaggerApplication that implement all of the above另一种方法是扩展实现上述所有内容的DaggerApplication

Now i can just inject MainActivity into the Mortgage Controller现在我可以将 MainActivity 注入 Mortgage Controller

   private final MainActivity mainActivity;


@Inject
public MortgageController(MainActivity mainActivity) {
    this.mainActivity = mainActivity;
}

For more information see this amazing article that helped me better understand this not so simple subject, and Google's Android-Architecture sample app an example project that among other things show how to implement Dagger2 properly.有关更多信息,请参阅这篇出色的文章,它帮助我更好地理解了这个不那么简单的主题,以及Google 的 Android-Architecture 示例应用程序一个示例项目,其中展示了如何正确实施 Dagger2。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 使用 Dagger 2 注入子类的最佳方法是什么? - What is the best way to inject subclasses using Dagger 2? 通过 Dagger 2 提供 RoomDatabase 时实现 .addCallback() 的正确方法是什么? - What is the proper way to implement .addCallback() when providing RoomDatabase via Dagger 2? 对于Dagger 2,从其他模块访问1个模块内的实例的最佳方法是什么? - For Dagger 2, what is the best way to access an instance inside 1 module from other modules? 实施计时器的最佳方法是什么? - What is the best way to implement the timer? 如果您正在尝试清洁架构,那么使用 Dagger 的最佳方式是什么? - What is the best way to use Dagger if you're attempting Clean Architecture? 用Dagger 2注入子类型的类的最佳方法是什么? - What is the best way to inject a class of a child type with Dagger 2? 使用ORMLite实现多对多关系的最佳方法是什么? - What is the best way to implement many-to-many relationships using ORMLite? 使用OnClick事件的最佳方法是什么? - What is the best way to use OnClick event? 在CakePHP 3.0中,实现不遵循CakePHP命名约定的Controller and Function的最佳方法是什么? - In CakePHP 3.0 what is the best way to implement a Controller and Function that doesn't follow CakePHP naming conventions? 在AsyncTask中获取/使用Context的最佳方法是什么? - What is the best way of getting / using Context inside AsyncTask?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM