关闭

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

标签: Android注入款架RoboGiuce
437人阅读 评论(0) 收藏 举报
分类:
githuab地址:

其中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 ;
    }
}

其中,使用时候的调用时
@Inject
private 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 app
class 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
{
@override
public void printName()
{
Log.i("TAG","i am Foo1");
}
}
//
public class Foo2 implement IFoo
{
@override
public 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") //对应Foo2
IFoo ifoo;
@Inject
@Named("Foo")//对应Foo1
IFoo 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 @MyOtherAnnotation
IFoo 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) ;
最后使用
@Inject
Foo 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

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:56062次
    • 积分:438
    • 等级:
    • 排名:千里之外
    • 原创:31篇
    • 转载:0篇
    • 译文:0篇
    • 评论:4条
    个人github
    • https://github.com/liweijieok/
    最新评论