2017-06-07 19 views
9

Tôi đã triển khai dagger2 v2.2 trước đó nhưng bây giờ họ cũng đã thêm phần dagger.android. vì vậy tôi đang tạo dự án mẫu với điều đó.Cách sử dụng thực tế của "HasFragmentInjector" trong Dagger 2

Tôi biết về phương pháp cũ của @Provide@Modules@Components vv chú thích nhưng từ Dagger 2.8+ họ đã thêm thư viện android-hỗ trợ này cũng có một số Tiêm mới như @ActivityKey, @ContributesAndroidInjector, @ Subcomponent.Builder, vv

Vì vậy, câu hỏi của tôi là những lợi ích nó mang đến cho bảng.

Việc giải quyết các vấn đề như phương pháp Tiêm với lớp cơ sở có thể phù hợp với tất cả các lớp con không? hoặc bất kỳ lợi ích nào khác?

Câu hỏi thứ hai - HasFragmentInjector chỉ để tải phân đoạn bên trong hoạt động như chúng tôi đã từng sử dụng trình quản lý phân đoạn? hoặc tôi đang thiếu một số điều?

Vui lòng không downvote câu hỏi nhiều thông tin hơn cho tất cả người dùng thư viện vì tài liệu của thư viện không cung cấp câu trả lời như vậy.

+1

Từ kiến ​​thức rất hạn chế của tôi về dagger2 và đặc biệt là công cụ mới này, tôi có thể nói rằng bạn có thể sử dụng các lớp học hoạt động cơ sở và mảnh cơ sở để tiêm phụ thuộc cho các lớp con của họ. Đối với câu hỏi thứ hai, đó là cho dao găm để có được vòi phun mảnh được sử dụng để tiêm phụ thuộc vào các mảnh được tạo ra. Nhưng bạn vẫn phải sử dụng FragmentManager. –

+0

Ở đây tôi trích xuất mã liên quan đến con dao găm của mình, tôi không chắc nó có đúng không, nhưng nó hoạt động. https://gist.github.com/anonymous/45446b3bf2100d1c22520ebf82f0bff3 –

+0

@KrystianP. Cảm ơn thông tin nhưng tôi vẫn đang chờ câu trả lời rõ ràng. giúp tôi hiểu khái niệm một cách rõ ràng. – androidnoobdev

Trả lời

2

Official Documentation giải thích chủ đề này khá tốt trong phản đối của tôi.

Dù sao lợi ích chính là thay vì một cái gì đó như thế này

((SomeApplicationBaseType) getContext().getApplicationContext()) 
    .getApplicationComponent() 
    .newActivityComponentBuilder() 
    .activity(this) 
    .build() 
    .inject(this); 

Bạn chỉ có thể viết những dòng này, mà làm cho cuộc sống dễ dàng hơn cho tất cả mọi người.

AndroidInjection.inject(this); 
  1. Ít soạn sẵn, dễ dàng bảo trì.

  2. Cách tiếp cận trước là loại vi phạm khái niệm cơ bản về tiêm phụ thuộc, một lớp không biết bất kỳ chi tiết nào về cách thức phụ thuộc đang được tiêm.

15

Câu hỏi đầu tiên

Trong Dagger 2.8+ họ đã thêm thư viện này android-hỗ trợ cũng có một số chú thích mới như @ActivityKey, @ContributesAndroidInjector, @Subcomponent.Builder vv Vì vậy, câu hỏi của tôi là những gì có lợi cho nó mang đến bàn.

này đã được trả lời trong What are the advantages of using DispatchingAndroidInjector and the other dagger-android classes?

Liệu nó giải quyết vấn đề như không có một phương pháp bơm cho một lớp cơ sở có thể làm việc cho tất cả các lớp con?

Dagger 2 sử dụng tạo mã tại thời gian biên dịch để tiêm phụ thuộc. Trong đó, nó khác với các khung tiêm phụ thuộc khác như Guice kiểm tra các vị trí tiêm trong thời gian chạy. Để Dagger 2 hoạt động, bạn phải tại một số điểm xác định bất biến của vị trí tiêm.Do đó, bạn sẽ không bao giờ có thể viết một cái gì đó như:

void inject(Activity activity); 

bên trong thành phần Dagger 2 và nó có tiêm tất cả các hoạt động hay không.

Tuy nhiên, có nhiều cải tiến với các lớp mới có sẵn trong dagger-android. Trong khi đó, trước khi bạn sẽ phải viết:

void inject(MainActivity mainActivity); 

và vân vân cho mỗi vị trí tiêm khác nhau, bây giờ bạn có thể viết đoạn mã sau:

@Module(subcomponents = MainActivitySubcomponent.class) 
public abstract class MainActivityModule { 

    @Binds 
    @IntoMap 
    @ActivityKey(MainActivity.class) 
    abstract AndroidInjector.Factory<? extends Activity> mainActivityInjectorFactory(MainActivitySubcomponent.Builder builder); 
} 

và sau đó:

AndroidInjection.inject(this); 

bên trong của bạn MainActivity tại điểm thích hợp.

Câu hỏi thứ hai

HasFragmentInjector chỉ là để tải Fragment bên Hoạt động giống như chúng ta sử dụng để làm bằng FragmentManager? hoặc tôi đang thiếu cái gì đó?

HasFragmentInjector chỉ cần đánh dấu lớp mà Fragment sẽ nhận được AndroidInjector từ đó. Bạn có thể xem cho chính mình trong các mã on GitHub cho AndroidInjection#inject(Fragment fragment):

public static void inject(Fragment fragment) { 
    checkNotNull(fragment, "fragment"); 
    HasFragmentInjector hasFragmentInjector = findHasFragmentInjector(fragment); 
    Log.d(TAG, String.format(
     "An injector for %s was found in %s", 
     fragment.getClass().getCanonicalName(), 
     hasFragmentInjector.getClass().getCanonicalName())); 

    AndroidInjector<Fragment> fragmentInjector = hasFragmentInjector.fragmentInjector(); 
    checkNotNull(fragmentInjector,"%s.fragmentInjector() returned null", 
    hasFragmentInjector.getClass().getCanonicalName()); 
    fragmentInjector.inject(fragment); 
} 

Từ javadoc, phương pháp này bước đầu tiên phụ huynh-mảnh, sau đó các hoạt động, sau đó cuối cùng là ứng dụng để tìm HasFragmentInjector và sử dụng AndroidInjector<Fragment> để tiêm các trường của Fragment.

Tuy nhiên, sự hiện diện của HasFragmentInjector không có nghĩa là bạn nên bắt đầu sử dụng mảnh vỡ quản lý Dagger 2:

public class MainActivity { 

    @Inject CoffeeFragment coffeeFragment; //no! don't do this 
    @Inject TeaFragment teaFragment; //no! 

Bạn vẫn nên sử dụng cách thành ngữ của instantiating Những mảnh vỡ đó là sử dụng phương pháp nhà máy tĩnh. Dagger 2 sẽ thực hiện tiêm cho các trường bên trong Fragments khi số onAttach(Context context) của chúng được gọi khi bạn nói thêm phân đoạn bằng cách sử dụng một giao dịch hoặc bạn ủy thác cho một ViewPager. Thay vì ví dụ trên, đoạn mã sau là một Hoạt động rất đơn giản với một ViewPager và hai mảnh vỡ:

public class MainActivity extends AppCompatActivity implements HasSupportFragmentInjector { 

    @Inject 
    DispatchingAndroidInjector<Fragment> fragmentDispatchingAndroidInjector; 

    ViewPager mViewPager; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     AndroidInjection.inject(this); 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 
     BeveragesPagerAdapter beveragesPagerAdapter = new BeveragesPagerAdapter(getSupportFragmentManager()); 
     mViewPager = (ViewPager) findViewById(R.id.viewpager); 
     mViewPager.setAdapter(beveragesPagerAdapter); 
    } 

    class BeveragesPagerAdapter extends FragmentStatePagerAdapter { 

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

     @Override 
     public Fragment getItem(int i) { 
      switch (i) { 
       case 0: 
        return TeaFragment.instantiate(new Bundle()); 
       case 1: 
        return CoffeeFragment.instantiate(new Bundle()); 
       default: 
        throw new IllegalStateException(); 
      } 
     } 

     @Override 
     public int getCount() { 
      return 2; 
     } 

     @Override 
     public CharSequence getPageTitle(int position) { 
      return "tab " + (position + 1); 
     } 
    } 

    @Override 
    public AndroidInjector<Fragment> supportFragmentInjector() { 
     return fragmentDispatchingAndroidInjector; 
    } 
} 

Các FragmentStatePagerAdapter một cách chính xác xử lý việc quản lý các mảnh vỡ và chúng tôi không tiêm như các lĩnh vực bên trong MainActivity.

Các mảnh vỡ mình trông như thế này:

trong CoffeeFragment.java:

public class CoffeeFragment extends Fragment { 

    public static CoffeeFragment instantiate(@Nullable Bundle arguments) { 
     CoffeeFragment coffeeFragment = new CoffeeFragment(); 
     coffeeFragment.setArguments(arguments); 
     return coffeeFragment; 
    } 

    @Inject 
    @Named("Coffee") 
    Repository repository; 

    TextView textView; 

    @Override 
    public void onAttach(Context context) { 
     AndroidSupportInjection.inject(this); 
     super.onAttach(context); 
    } 

    @Nullable 
    @Override 
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 
     View v = inflater.inflate(R.layout.fragment_coffee, container, false); 
     textView = (TextView) v.findViewById(R.id.coffee_textview); 
     return v; 
    } 

    @Override 
    public void onResume() { 
     textView.setText(repository.retrieve()); 
    } 
} 

trong CoffeeFragmentModule.java:

@Module(subcomponents = CoffeeFragmentSubcomponent.class) 
public abstract class CoffeeFragmentModule { 

    @Binds 
    @Named("Coffee") 
    abstract Repository repository(CoffeeRepository coffeeRepository); 

    @Binds 
    @IntoMap 
    @FragmentKey(CoffeeFragment.class) 
    abstract AndroidInjector.Factory<? extends Fragment> bindCoffeeFragmentInjectorFactory(CoffeeFragmentSubcomponent.Builder builder); 
} 

trong CoffeeFragmentSubcomponent.java:

@Subcomponent 
public interface CoffeeFragmentSubcomponent extends AndroidInjector<CoffeeFragment> { 

    @Subcomponent.Builder 
    abstract class Builder extends AndroidInjector.Builder<CoffeeFragment> {} 
} 

trong CoffeeRepository.java:

public class CoffeeRepository implements Repository { 

    @Inject 
    public CoffeeRepository() { 
    } 

    @Override 
    public String retrieve() { 
     return "Coffee!!!!"; 
    } 
} 
+0

Cảm ơn câu trả lời. Tôi vẫn đang tìm một số câu trả lời trước khi bắt đầu sử dụng dao găm trong dự án tiếp theo của tôi. và tôi sẽ không có sẵn trong vài ngày tới vì vậy nếu bạn tìm thấy thêm thông tin xin vui lòng cho tôi biết. và tôi đang tặng tiền thưởng cho bạn và giữ nó ... – androidnoobdev

Các vấn đề liên quan