热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

如何使用dagger2将活动注入适配器

如何解决《如何使用dagger2将活动注入适配器》经验,为你挑选了2个好方法。

Android Studio 3.0 Canary 8

我正在尝试将我的MainActivity注入我的适配器.但是,我的解决方案工作正常,但我认为它的代码味道并不是正确的方法.

我的适配器代码段看起来像这样,但我不喜欢这是我必须转换ActivityMainActivity:

public class RecipeAdapter extends RecyclerView.Adapter {
    private List recipeList = Collections.emptyList();
    private Map viewHolderFactories;
    private MainActivity mainActivity;

    public RecipeAdapter(Activity activity, Map viewHolderFactories) {
        this.recipeList = new ArrayList<>();
        this.viewHolderFactories = viewHolderFactories;
        this.mainActivity = (MainActivity)activity;
    }

    @Override
    public RecipeListViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
        /* Inject the viewholder */
        final RecipeListViewHolder recipeListViewHolder = viewHolderFactories.get(Constants.RECIPE_LIST).createViewHolder(viewGroup);

        recipeListViewHolder.itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                /* Using the MainActivity to call a callback listener */
                mainActivity.onRecipeItemClick(getRecipe(recipeListViewHolder.getAdapterPosition()));
            }
        });

        return recipeListViewHolder;
    }
}

在我的模块中,我在模块的构造函数中传递Activity并将其传递给Adapter.

@Module
public class RecipeListModule {
    private Activity activity;

    public RecipeListModule() {}

    public RecipeListModule(Activity activity) {
        this.activity = activity;
    }

    @RecipeListScope
    @Provides
    RecipeAdapter providesRecipeAdapter(Map viewHolderFactories) {
        return new RecipeAdapter(activity, viewHolderFactories);
    }
}

在我的应用程序类中,我创建组件,我使用SubComponent作为适配器.在这里,我必须通过我不确定是一个好主意的活动.

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

    applicatiOnComponent= createApplicationComponent();
    recipeListCompOnent= createRecipeListComponent();
}

public BusbyBakingComponent createApplicationComponent() {
    return DaggerBusbyBakingComponent.builder()
            .networkModule(new NetworkModule())
            .androidModule(new AndroidModule(BusbyBakingApplication.this))
            .exoPlayerModule(new ExoPlayerModule())
            .build();
}

public RecipeListComponent createRecipeListComponent(Activity activity) {
    return recipeListCompOnent= applicationComponent.add(new RecipeListModule(activity));
}

我的片段我这样注入:

@Inject RecipeAdapter recipeAdapter;

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

        ((BusbyBakingApplication)getActivity().getApplication())
                .createRecipeListComponent(getActivity())
                .inject(this);
    }

即使上面的设计有效,我认为这是一个代码味道,因为我必须将Activity转换为MainActivity.我之所以使用Activity,是因为我想让这个模块更通用.

只是想知道是否有更好的方法

===============更新使用接口

接口

public interface RecipeItemClickListener {
    void onRecipeItemClick(Recipe recipe);
}

履行

public class RecipeItemClickListenerImp implements RecipeItemClickListener {
    @Override
    public void onRecipeItemClick(Recipe recipe, Context context) {
        final Intent intent = Henson.with(context)
                .gotoRecipeDetailActivity()
                .recipe(recipe)
                .build();

        context.startActivity(intent);
    }
}

在我的模块中,我有以下提供者

@Module
public class RecipeListModule {
    @RecipeListScope
    @Provides
    RecipeItemClickListener providesRecipeItemClickListenerImp() {
        return new RecipeItemClickListenerImp();
    }

    @RecipeListScope
    @Provides
    RecipeAdapter providesRecipeAdapter(RecipeItemClickListener recipeItemClickListener, Map viewHolderFactories) {
        return new RecipeAdapter(recipeItemClickListener, viewHolderFactories);
    }
}

然后我通过RecipeAdapter中的构造函数注入使用它

public class RecipeAdapter extends RecyclerView.Adapter {
    private List recipeList = Collections.emptyList();
    private Map viewHolderFactories;
    private RecipeItemClickListener recipeItemClickListener;

    @Inject /* IS THIS NESSESSARY - AS IT WORKS WITH AND WITHOUT THE @Inject annotation */
    public RecipeAdapter(RecipeItemClickListener recipeItemClickListener, Map viewHolderFactories) {
        this.recipeList = new ArrayList<>();
        this.viewHolderFactories = viewHolderFactories;
        this.recipeItemClickListener = recipeItemClickListener;
    }

    @Override
    public RecipeListViewHolder onCreateViewHolder(final ViewGroup viewGroup, int i) {
        /* Inject the viewholder */
        final RecipeListViewHolder recipeListViewHolder = viewHolderFactories.get(Constants.RECIPE_LIST).createViewHolder(viewGroup);

        recipeListViewHolder.itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                recipeItemClickListener.onRecipeItemClick(getRecipe(recipeListViewHolder.getAdapterPosition()), viewGroup.getContext());
            }
        });

        return recipeListViewHolder;
    }
}

只有一个问题,是RecipeAdapter中构造函数的@Inject注释需要.因为它可以使用或不使用@Inject.



1> Yossi Segev..:

不要将活动传递给适配器 - 这是一个非常糟糕的做法.

仅注入您关心的字段.

在您的示例中:将接口传递到适配器以跟踪项目单击.



2> David Medenj..:

如果你需要,MainActivity那么你也应该提供它.而不是为您的模块Activity声明MainActivity.

@Module
public class RecipeListModule {
  private MainActivity activity;

  public RecipeListModule(MainActivity activity) {
    this.activity = activity;
  }
}

你的适配器应该只是请求它( Android Framework类型的构造函数注入!)

@RecipeListScope
class RecipeAdapter {

  @Inject
  RecipeAdapter(MainActivity activity,
          Map viewHolderFactories) {
    // ...
  }

}

如果你想要你的模块使用Activity而不是MainActivity那么你需要声明一个已经提到过的接口.然后,适配器会将接口声明为其依赖项.

但在某些模块中,您仍然需要将该接口绑定到您的MainActivity模块,并且一个模块需要知道如何提供依赖项.

// in some abstract module
@Binds MyAdapterInterface(MainActivity activity) // bind the activity to the interface

解决问题的更新部分

只有一个问题,是@InjectRecipeAdapter中构造函数的注释需求.因为它可以使用或不使用@Inject.

它没有它,因为你还没有使用构造函数注入.你还在调用构造自己providesRecipeAdapter().作为一般的经验法则 - 如果你想正确使用Dagger - 不要自称new.如果你new想问自己是否可以使用构造函数注入.

您显示的相同模块可以编写如下,使用@Binds绑定实现到接口,并实际使用构造函数注入来创建适配器(这就是为什么我们不必为它编写任何方法!更少的代码到维护,减少错误,更易读的类)

如你所见,我不需要new自己使用--Dagger会为我创建物体.

public abstract class RecipeListModule {
  @RecipeListScope
  @Binds
  RecipeItemClickListener providesRecipeClickListener(RecipeItemClickListenerImp listener);
}


推荐阅读
  • 本文整理了Java中javax.lang.model.util.Types.getNullType()方法的一些代码示例,展示了Types.getNullT ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • Python正则表达式学习记录及常用方法
    本文记录了学习Python正则表达式的过程,介绍了re模块的常用方法re.search,并解释了rawstring的作用。正则表达式是一种方便检查字符串匹配模式的工具,通过本文的学习可以掌握Python中使用正则表达式的基本方法。 ... [详细]
  • Linux重启网络命令实例及关机和重启示例教程
    本文介绍了Linux系统中重启网络命令的实例,以及使用不同方式关机和重启系统的示例教程。包括使用图形界面和控制台访问系统的方法,以及使用shutdown命令进行系统关机和重启的句法和用法。 ... [详细]
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • JavaSE笔试题-接口、抽象类、多态等问题解答
    本文解答了JavaSE笔试题中关于接口、抽象类、多态等问题。包括Math类的取整数方法、接口是否可继承、抽象类是否可实现接口、抽象类是否可继承具体类、抽象类中是否可以有静态main方法等问题。同时介绍了面向对象的特征,以及Java中实现多态的机制。 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • Android JSON基础,音视频开发进阶指南目录
    Array里面的对象数据是有序的,json字符串最外层是方括号的,方括号:[]解析jsonArray代码try{json字符串最外层是 ... [详细]
  • 自动轮播,反转播放的ViewPagerAdapter的使用方法和效果展示
    本文介绍了如何使用自动轮播、反转播放的ViewPagerAdapter,并展示了其效果。该ViewPagerAdapter支持无限循环、触摸暂停、切换缩放等功能。同时提供了使用GIF.gif的示例和github地址。通过LoopFragmentPagerAdapter类的getActualCount、getActualItem和getActualPagerTitle方法可以实现自定义的循环效果和标题展示。 ... [详细]
  • 推荐:看到如此多的MVP+Dagger2+Retrofit+Rxjava项目,轻松拿star,心动了吗?看到身边的朋友都已早早在项目中使用这些技术,而你还不会,失落吗?MVPArm ... [详细]
  • #前言AndroidArchitectureComponents是谷歌在GoogleIO2017发布的。官方的描述:https:developer.android.google.c ... [详细]
  • 特殊字符转义表字符十进制转义字符"&&不断开空格(non-breakingspace)最常用的转义字符列表显示说明实体名称十进制编号半方大的空 ... [详细]
author-avatar
多盟乄丶
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有