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!!!!";
}
}
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. –
Ở đâ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 –
@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