当前位置: 首页 > 面试题库 >

Dagger 2:使用@Named获取同一对象的多个实例时出错

宋运锋
2023-03-14
问题内容

我怎样才能获得多个具有相同返回类型的实例,如游标

例如 :

Module
@CursorScope
public class CursorModule {


    @Provides
    Cursor provideSongCursor(
            @Named("Song") Musician musician) {
        return musician.getApplicationContext().getContentResolver().query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
                new String[]{
                        BaseColumns._ID,
                        MediaStore.Audio.AudioColumns.TITLE,
                        MediaStore.Audio.AudioColumns.ARTIST,
                        MediaStore.Audio.AudioColumns.ALBUM,
                        MediaStore.Audio.AudioColumns.DURATION
                }, MediaStore.Audio.AudioColumns.IS_MUSIC + "=1", null, null);
    }

    @Provides
    Cursor provideAlbumCursor(
            @Named("Album") Musician musician) {
        return musician.getApplicationContext().getContentResolver().query(MediaStore.Audio.Albums.EXTERNAL_CONTENT_URI,
                new String[]{
                        BaseColumns._ID,
                        MediaStore.Audio.AlbumColumns.ALBUM,
                        MediaStore.Audio.AlbumColumns.ARTIST,
                        MediaStore.Audio.AlbumColumns.NUMBER_OF_SONGS,
                        MediaStore.Audio.AlbumColumns.FIRST_YEAR
                }, null, null, null);
    }

    @Provides
    Cursor provideArtistCursor(@Named("Artist") Musician musician) {
        return musician.getApplicationContext().getContentResolver().query(MediaStore.Audio.Artists.EXTERNAL_CONTENT_URI,
                new String[] {
                        BaseColumns._ID,
                        MediaStore.Audio.ArtistColumns.ARTIST,
                        MediaStore.Audio.ArtistColumns.NUMBER_OF_ALBUMS,
                        MediaStore.Audio.ArtistColumns.NUMBER_OF_TRACKS
                }, null, null,null);
    }

    @Provides
    Cursor provideGenreCursor(
            @Named("Genres") Musician musician) {
        return musician.getApplicationContext().getContentResolver().query(MediaStore.Audio.Genres.EXTERNAL_CONTENT_URI,
                new String[] {
                        BaseColumns._ID,
                        MediaStore.Audio.GenresColumns.NAME
                }, null, null, null);
    }

    @Provides
    Cursor providePlaylistCursor(@Named("Playlist") Musician musician) {
        return musician.getApplicationContext().getContentResolver().query(MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI,
                new String[] {
                        BaseColumns._ID,
                        MediaStore.Audio.PlaylistsColumns.NAME
                }, null, null, null);
    }
}

提供在

@CursorScope
@Subcomponent(modules = CursorModule.class)
public interface CursorComponent {
    Cursor cursor();
}

我得到这个错误

Error:(17, 11) Gradle: error: android.database.Cursor is bound multiple times:
@Provides android.database.Cursor com.merkmod.musician.dependency.CursorModule.provideSongCursor(@Named("Song") com.merkmod.musician.application.Musician)
@Provides android.database.Cursor com.merkmod.musician.dependency.CursorModule.provideAlbumCursor(@Named("Album") com.merkmod.musician.application.Musician)
@Provides android.database.Cursor com.merkmod.musician.dependency.CursorModule.provideArtistCursor(@Named("Artist") com.merkmod.musician.application.Musician)
@Provides android.database.Cursor com.merkmod.musician.dependency.CursorModule.provideGenreCursor(@Named("Genres") com.merkmod.musician.application.Musician)
@Provides android.database.Cursor com.merkmod.musician.dependency.CursorModule.providePlaylistCursor(@Named("Playlist") com.merkmod.musician.application.Musician)

我制作了Cursor的多个实例,并在提供程序级别首先使用@Named进行了注释,然后开始出现错误,无法提供@Provides注释,因此我转向在构造函数中使用它

就像上面的代码一样。问题是一次又一次地运行一个周期,我就像被困在完成光标工作上一样,任何帮助都会得到解决。


问题答案:

所以最后我得到了我自己的问题的答案,它本身就是组件的一部分,您知道软件开发太忙了,以至于当您退出公司时,它也成为了更大的负担。

因此,以上所有方法都是一种简单的方法,我用sharepreference制作了另一个示例,因为我的笔记本电脑在archlinux上崩溃了。

所以这是我生成的代码的片段。

所以我唯一要做的就是应该从组件接口中删除光标注入参数。

摘录可能会帮助人们。

零件 :

@Singleton
@Component(modules = {MusicianModule.class, SharedPreferencesModule.class})
public interface MusicianComponent {
    void inject(MainActivity mainActivity);
    Musician musician();
}

模块:

@Module
public class SharedPreferencesModule {

    @Provides
    @Named("default")
    SharedPreferences provideDefaultsharedPreferences(Musician musician) {
        return musician.getSharedPreferences("default", Context.MODE_PRIVATE);
    }

    @Provides
    @Named("secret")
    SharedPreferences provideSecretsharedPreferences(Musician musician) {
        return musician.getSharedPreferences("secret", Context.MODE_PRIVATE);
    }
}

音乐家模块:

@Module
public class MusicianModule {

    private Musician musician;

    public MusicianModule(Musician musician) {
        this.musician = musician;
    }

    @Provides @Singleton
    Musician providemusician() {
        return musician;
    }

    @Provides @Singleton
    Application provideapplication(Musician musician) {
        return musician;
    }
}

应用类别:

public class Musician extends Application {

    private MusicianComponent musicianComponent;
    @Override
    public void onCreate() {
        resolvedependency();
        super.onCreate();
    }


    private void resolvedependency() {
        musicianComponent = DaggerMusicianComponent.builder()
                .musicianModule(new MusicianModule(this))
                .sharedPreferencesModule(new SharedPreferencesModule())
                .build();
    }


    public static MusicianComponent getMusicianComponent(Context context) {
        return ((Musician)context.getApplicationContext()).musicianComponent;
    }
}

然后在MainActivity中注入:

public class MainActivity extends AppCompatActivity {

    /**
     * The {@link android.support.v4.view.PagerAdapter} that will provide
     * fragments for each of the sections. We use a
     * {@link FragmentPagerAdapter} derivative, which will keep every
     * loaded fragment in memory. If this becomes too memory intensive, it
     * may be best to switch to a
     * {@link android.support.v4.app.FragmentStatePagerAdapter}.
     */
    private SectionsPagerAdapter mSectionsPagerAdapter;



    /**
     * The {@link ViewPager} that will host the section contents.
     */
    private ViewPager mViewPager;

    @Inject @Named("default")
    SharedPreferences defSharedPreferences;

    @Inject @Named("secret")
    SharedPreferences secSharedPreferences;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Musician.getMusicianComponent(this).inject(this);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        // Create the adapter that will return a fragment for each of the three
        // primary sections of the activity.
        mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
        defSharedPreferences.edit().putString("status", "worked").apply();
        secSharedPreferences.edit().putString("status", "worked").apply();

        // Set up the ViewPager with the sections adapter.
        mViewPager = (ViewPager) findViewById(R.id.container);
        mViewPager.setAdapter(mSectionsPagerAdapter);

        TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
        tabLayout.setupWithViewPager(mViewPager);
    }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    /**
     * A placeholder fragment containing a simple view.
     */
    public static class PlaceholderFragment extends Fragment {
        /**
         * The fragment argument representing the section number for this
         * fragment.
         */
        private static final String ARG_SECTION_NUMBER = "section_number";

        public PlaceholderFragment() {
        }

        /**
         * Returns a new instance of this fragment for the given section
         * number.
         */
        public static PlaceholderFragment newInstance(int sectionNumber) {
            PlaceholderFragment fragment = new PlaceholderFragment();
            Bundle args = new Bundle();
            args.putInt(ARG_SECTION_NUMBER, sectionNumber);
            fragment.setArguments(args);
            return fragment;
        }

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                 Bundle savedInstanceState) {
            View rootView = inflater.inflate(R.layout.fragment_song, container, false);
            TextView textView = (TextView) rootView.findViewById(R.id.section_label);
            textView.setText(getString(R.string.section_format, getArguments().getInt(ARG_SECTION_NUMBER)));
            return rootView;
        }
    }

    /**
     * A {@link FragmentPagerAdapter} that returns a fragment corresponding to
     * one of the sections/tabs/pages.
     */
    public class SectionsPagerAdapter extends FragmentPagerAdapter {

        public SectionsPagerAdapter(FragmentManager fm) {
            super(fm);
        }

        @Override
        public Fragment getItem(int position) {
            // getItem is called to instantiate the fragment for the given page.
            // Return a PlaceholderFragment (defined as a static inner class below).
            return PlaceholderFragment.newInstance(position + 1);
        }

        @Override
        public int getCount() {
            // Show 3 total pages.
            return 3;
        }

        @Override
        public CharSequence getPageTitle(int position) {
            switch (position) {
                case 0:
                    return "SECTION 1";
                case 1:
                    return "SECTION 2";
                case 2:
                    return "SECTION 3";
            }
            return null;
        }
    }


 类似资料:
  • 我有一个JPA实体和一个子实体列表。在这种情况下,是一个附加了角色的用户实体。 它看起来(有点简化-省略了一些字段/方法)如下: 如果是入侵,角色实体非常简单。 当我为每个用户添加两个用户和几百个角色时,当我列出用户时,我会得到一个疯狂的行为。每个用户都会被列出几百次(相同的用户=相同的唯一id)。 有问题的代码: 然而,当我只是访问数据库并执行select语句时,它看起来很好。每个用户只存在一次

  • 我是使用Dagger2的新手(我一直使用Koin),我正在尝试实现一个简单的示例,但我真的不知道我缺少了什么。这就是我目前得到的。 app.gradle: 应用模块。kt: AppComponent。kt: TestClass。千吨 pp.kt: MainActivity.kt: 错误:testClass==null

  • 我正在设计一个模块,可以支持不同的数据源。我的模块获取用户的公司id作为输入,并且我必须根据公司id调用适当的类。我正在尝试合并一些好的设计,尽可能避免条件语句。 我有一个使用此方法的FetchDataSource单例类。 “communicator”是一个接口,而communicator映射将返回适当的实例。这是同一个单例类中的populateCommunicatorMap()方法。

  • Gamma等人所说的设计模式 考虑对象聚合和熟悉之间的区别,以及它们在编译和运行时的表现方式。 聚合意味着一个对象拥有或负责另一个对象。一般来说,我们所说的一个物体具有或是另一个物体的一部分。聚合意味着聚合对象及其所有者具有相同的生存期。 熟人关系意味着一个对象仅仅知道另一个对象。有时熟人关系被称为“关联”或“使用”关系。熟人对象可能会请求彼此的操作,但它们并不对彼此负责。熟人关系比聚合关系弱,表

  • 对不起,如果这是一个微不足道的问题,我是新的指南。假设我有下面这个类: 然后在其他地方我想做: 我希望有两个“MyClass”实例,一个名为“foo ”,一个名为“bar ”(也就是说,它们中的每一个都有一个不同的依赖实例)。我如何将这两个实例添加到我的注入器中,如何用“injector.getInstance”检索它们中的每一个? 我不想为每个可能的依赖项创建一个“MyClass”的子类。 谢谢

  • 我正在尝试编写一个简单的应用程序,其中包含一个跟踪每个用户支付的款项的表和一个包含每个用户支付的总金额(所有付款的总和)的第二个表。目前,两个表都有相同的字段(firstName、lastName、金额),我已经将它们从同一个Java类映射到多个表,我无法将该类映射到多个表。对此有什么简单的解决方案吗?