Android开发使用RoboGuice3.0框架进行注入

来源:互联网 发布:unity3d 布料系统 编辑:程序博客网 时间:2024/05/16 13:55
githuab地址:
https://github.com/roboguice/roboguice/wiki/InstallationGradle
https://github.com/google/guice/wiki

其中3.0之后没有的方法EventManager的fire(),RoboApplication (2.*之后就没了),还有就是设置model,现在好像只能通过xml文件中设置。
Android studio设置
在对应的model的dependencies添加如下:
compile 'org.roboguice:roboguice:3.+'provided 'org.roboguice:roboblender:3.+'
再添加一个新的project.dependencies ,也是在model的build.gradle中添加
project .dependencies {    // For the optional Nullable annotation    compile 'com.google.code.findbugs:jsr305:1.3.9'}

这样子就可以使用RoboGuice

首先,RoboGuice是一个注入框架,跟AndroidAnnotation,Dragger,ButterKnife一样,是简化我们的代码,带来方便的。
使用:
Activity中使用,Activity需要继承RoboActivity
1,为Activity使用布局
@ContentView  示例
@ContentView(R.layout.activity_main)public class MainActivity extends RoboActivity {.....}

为View初始化,使用@IntjectView
@InjectView(R.id.textview)    private TextView tv;
资源:@InjectResource所有德邦res目录下的资源都可以通过如下方式找到,比如动画,String,color,像素等
@InjectResource(R.string.app_name)    String name;
获取系统的一些系统服务,通过@Inject标签完成初始化
@Inject Vibrator vibrator;@Inject NotificationManager notificationManager;
包括:
@Inject ContentResolver contentResolver;  @Inject AssetManager assetManager;  @Inject Resources resources;  @Inject LocationManager locationManager;  @Inject WindowManager windowManager;  @Inject LayoutInflater layoutInflater;  @Inject ActivityManager activityManager;  @Inject PowerManager powerManager;  @Inject AlarmManager alarmManager;  @Inject NotificationManager notificationManager;  @Inject KeyguardManager keyguardManager;  @Inject SearchManager searchManager;  @Inject Vibrator vibrator;  @Inject ConnectivityManager connectivityManager;  @Inject WifiManager wifiManager;  @Inject InputMethodManager inputMethodManager;  @Inject SensorManager sensorManager;  @Inject Application application;  @Inject Context context;

@Inject +类名+变量 进行初始化
有几种情况
1,这个类没有构造器,比如
import android.util.Log ;import com.google.inject.Inject ;/*** Created by user on 2015/11/18.*/public class Bar {    private int agr;    private int getAgr ()    {        return agr;    }    public void setAgr()    {        this .agr = agr;    }}
2.全部的构造器没有添加@Inject,然后还带有一个空的构造器
比如上面代码添加
public Bar(){   }public Bar(int a){    this .agr = a ;}
3,构造器中的参数列表不带有基本数据类型,然后有一个构造器,是使用@Inject指定
比如下面,被调用的就是使用了@Inject的构造器,但是没有东西传入了,这种情况下,有没有空的构造器也是可以的(没有使用Named注解的时候)
package retrofit.com.example.user.roboguicedemo ;import android.util.Log ;import com.google.inject.Inject ;/*** Created by user on 2015/11/18.*/public class Bar {    private String  agr;    private String name;    @Inject    public Bar(String a)    {        this .agr = a ;        Log. i("TAG", "被调用,但是传入来的" +agr) ;    }   public Bar(String a,String b)   {       this .agr = a ;       this. name = b;   }    public String getAgr() {        return agr;    }    public void setAgr(String agr) {        this .agr = agr ;    }    public Bar()    {    }    public String getName() {        return name;    }    public void setName(String name) {        this .name = name ;    }}

其中,使用时候的调用时
@Injectprivate Bar bar ;
即可完成初始化

这样子就完成了初始化
还有,我们可以自己为一个类使用注解添加空构造器,
就是
class MyActivity extends RoboActivity {    @Inject Foo foo; // this will basically call new Foo();}
即可
但被使用的时候,就会自动调用空的构造器了
单例模式:@singleton,这样子声明就是一个单例了,可能会内存溢出(直到应用被销毁才会被回收)
@Singleton //a single instance of Foo is now used though the whole appclass Foo {}

使用一个上下文的单例@ContextSingleton,,这样子的变量实例的生命周期就跟他所在的上下文相关联了,上下文一般是四大组件或者是Application中使用存在
比如
public MyActivity extends RoboActivity {  @Inject Foo foo;  @Inject Bar bar;}public class Foo {  @Inject Bar bar;}@ContextSingletonpublic class Bar {}
然后
new MyRoboActivity().foo != new MyRoboActivity().foo;//上下文不一样  MyRoboActivity a = new MyRoboActivity();a.bar == a.foo.bar//上下文一样
注意一定:在不同的Fragment中使用,然后这些Fragment绑定到相同的Activity的时候,他们的单例还是存在效果,就是还是一样的。
还有一种方式,就是通过bind的时候制定单例,
比如  
bind(TransactionLog.class) .to(InMemoryTransactionLog.class) .in(Singleton.class);

这样子,就可以不要上面的那个@ Singleton注解了
自定义binding
就是使用子类的多态
比如现在是这样子,有一个父类(可以是接口,可以使实现或者抽象类)
public interface IFoo{void printName();}
子类
public class Foo1 implement IFoo{@overridepublic void printName(){Log.i("TAG","i am Foo1");}}//public class Foo2 implement IFoo{@overridepublic void printName(){Log.i("TAG","i am Foo2");}}

然后,binding,自定义一个继承AbstractModule的类
然后,在里面的configure中进行绑定
示例代码:
package retrofit.com.example.user.roboguicedemo ;import com.google.inject.AbstractModule ;import com.google.inject.Binder ;import com.google.inject.Scopes ;import com.google.inject.Singleton ;import com.google.inject.binder.AnnotatedBindingBuilder ;import com.google.inject.name.Named ;import com.google.inject.name.Names ;/*** Created by user on 2015/11/18.*/public class MyModule extends AbstractModule {    @Override    protected void configure() {        Binder binder = binder();        //前面是接口父类,后面是子类        binder.bind(IFoo.class).annotatedWith(Names. named( "Foo1")).to(Foo.class );        binder.bind(IFoo.class).annotatedWith(Names. named( "Foo2")).to(OtherFoo.class );//        bind(IFoo.class).toInstance(new Foo());    }    @Override    protected <T> AnnotatedBindingBuilder< T> bind (Class<T> clazz) {        return super .bind(clazz);    }}

然后在清单文件中的applica中添加(是在application节点中添加)
<meta-data android:name="roboguice.modules"           android:value="retrofit.com.example.user.roboguicedemo.MyModule" />
使用:
@Inject@Named("OtherFoo") //对应Foo2IFoo ifoo;@Inject@Named("Foo")//对应Foo1IFoo iFoo;
这样子,对应的变量调用printName()方法就可以调用到对应的方法了
还有一种实现方式是自定义注解
自定义注解:
package retrofit.com.example.user.roboguicedemo ;import com.google.inject.BindingAnnotation ;import java.lang.annotation.Documented ;import java.lang.annotation. ElementType;import java.lang.annotation.Inherited ;import java.lang.annotation.Retention ;import java.lang.annotation.RetentionPolicy ;import java.lang.annotation.Target ;/*** Created by user on 2015/11/18.*/@BindingAnnotation@Retention(RetentionPolicy. RUNTIME)@Documented@Inherited@Target({ElementType .TYPE,ElementType. FIELD,ElementType .METHOD,ElementType. PARAMETER})public @interface MyAnnotation {}
还有一个只需要改了名字即可
然后,使用:
把原来的bind去掉,改成MyOtherAnnotation即可(随便)
ind(IFoo. class).annotatedWith(MyAnnotation .class).to(Foo. class);bind(IFoo.class).annotatedWith( MyOtherAnnotation.class ).to(OtherFoo.class) ;
使用
@Inject @MyAnnotation IFoo ifoo; @Inject @MyOtherAnnotationIFoo iFoo;

绑定Bindings 可以有下面几种类型:

  • Linked bindings
  • instance bindings
  • @provider methods
  • provider bindings
  • constructor bindings
  • untargetted bindings
  • built-in bindings
  • just-in-time bindings
  • providers 等
1,Linked bindings允许链接,比如
现在有三个类,A,B,C,其中B继承或者实现A,C继承或者实现B
那么,在module中的configure中使用如下:
bind(A.class).to(B.class);bind(B.class).to(C.class);
在使用的时候,@Inject A vir ;//得到的示例是C的实例
2,instance bindings
一般用于常见简单类型,比如String Integer,
定义(在configure中):
bind(Integer.class) .annotatedWith(Names.named("width")) .toInstance(100);bind(Integer.class) .annotatedWith(Names.named("height")) .toInstance(120);
以后使用@Named("name")就可以获得他的值
bind(String. class).annotatedWith(Names.named ("Name" )).toInstance("liweijie") ;bind(Integer.class)        .annotatedWith(Names.named ("age" ))        .toInstance(120 );

用途一般是在构造函数当中,例如
@Inject Foo(@Named( "Name")String name) {    this .name = name ;    Log.i("TAG" , name + "=name" );}
这样子是固定了条用@Injec Foo的时候,传入的参数是liweijie
在其他地方使用,可能为null
3,@Provider method
这个方法必须定义在模块中(Module),而且必须使用@Provides 标注,在个方法的返回类型则绑定到这个方法返回的对象实例。
比如:
@Provides @Named ("FooInstane")Foo provider(){    return new Foo("hello world") ;}
使用
@Inject@Named("FooInstane")Foo fooInsatece;
这样子,就为fooInstance赋值。
4,provider bindings
当有一些比较复杂的数据的组合而成的对象的时候,我们通过接口和实现,然后通过
其中
bind(A.class).toProvider(B.class);
来实现。例如
public class MyProvider implements Provider<Foo> {    @Override    public Foo get() {        return new Foo("hello guangzhou") ;    }}
然后绑定
bind (Foo.class ).toProvider(MyProvider.class) ;
最后使用
@InjectFoo foo;
即可获得实例
5,untargetted bindings
Untargetted Bindings不含to语句。
比如;
bind(MyConcreteClass.class);bind(AnotherConcreteClass.class).in(Singleton.class);

一般用于含有@ImplementedBy 和@ProvidedBy
但是,加入需要annotationWith(...)就需呀to,也就是taget,哪怕是本类,比如
bind(MyConcreteClass.class) .annotatedWith(Names.named("foo")) .to(MyConcreteClass.class);bind(AnotherConcreteClass.class) .annotatedWith(Names.named("foo")) .to(AnotherConcreteClass.class) .in(Singleton.class);
6 “即时绑定(Just-in-time Bindings)
    a,@ImplementedBy 
比如:
@ImplementedBy(PayPalCreditCardProcessor.class)public interface CreditCardProcessor{ChargeResult charge(String amount, CreditCard creditCard) throws UnreachableException;}
等价于:
bind(CreditCardProcessor.class)2 .to(PayPalCreditCardProcessor.class);
假如他定义了从Interface到实现的依赖,一般不建议使用,当他们都存在的时候,优先使用bind的
     b,@ProvidedBy
比如
@ProvidedBy(DatabaseTransactionLogProvider.class)public interface TransactionLog{void logConnectException(UnreachableException e);void logChargeResult(ChargeResult result);}
等价于
bind(TransactionLog.class) .toProvider(DatabaseTransactionLogProvider.class);
都存在的时候有限使用bind。
7,使用Exter
就是用于Budnle之间传值
  Intent di = new Intent();  di.setClass(context, InjectExtraReceiver.class) ;  di.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);  di.putExtra("Extra1","Message1");  di.putExtra("Extra2","Message2");  context.startActivity(di);
这些,我们都是按照原来之前的传递拼装就好,但是,到了被启动的Activity,可以使用如下找到他的值,其中options =true表示为可选,当没有这个值的时候是null 
  @InjectExtra ("Extra1" ) String extra1;  @InjectExtra ("Extra2" ) String extra2;  @InjectExtra (value="Extra3" , optional=true) String extra3;
9,Events 

Roboguice 提供了对Context 生命周期相关的事件的send 和receive ,系统缺省支持的事件为:

* OnActivityResultEvent* OnConfigurationChangedEvent* OnContentChangedEvent* OnContentViewAvailableEvent* OnCreateEvent* OnDestroyEvent* OnNewIntentEvent* OnPauseEvent* OnRestartEvent* OnResumeEvent* OnStartEvent* OnStopEvent
@observes 只能应用到方法上,而不能应用到构造函数上

常见错误:
11-18 08:04:09.068 2928-2928/retrofit.com.example.user.roboguicedemo E/AndroidRuntime: FATAL EXCEPTION: main
11-18 08:04:09.068 2928-2928/retrofit.com.example.user.roboguicedemo E/AndroidRuntime: java.lang.RuntimeException: Unable to start activity ComponentInfo{retrofit.com.example.user.roboguicedemo/retrofit.com.example.user.roboguicedemo.MainActivity}: com.google.inject.ConfigurationException: Guice configuration errors:
解决办法,应该是有些地方使用注解不合理,比如只有Named却把Inject也添加上了

























0 0
原创粉丝点击