Android开发:一些有用的库(第一部分)

263 篇文章 2 订阅
164 篇文章 0 订阅
Android Development: Some useful libraries (part I)

你好! 从我自己的经验。 我想出了这个可能最常使用并获得社群批准的库名单(也是谷歌的官方名单)。 您可能不需要为每个应用程序包括所有这些库,但这里的想法是要选择正确的。

支持库
从Google向旧版本的Android提供新的API和稳定性修复程序。 有几个版本,有特定的最低SDK版本,其中一些可以帮助你找到问题,并改进你的代码,如android注释支持:
compile 'com.android.support:support-v4:x.y.z'
compile 'com.android.support:appcompat-v7:x.y.z'
compile 'com.android.support:support-v13:x.y.z'
compile 'com.android.support:design:x.y.z'
compile 'com.android.support:support-annotations:x.y.z'
...
Multidex支持库
如果你曾经遇到超过65k方法错误,而你建立你的应用程序,这可能是你的解决(但这应该是最后的手段,你应该尝试剥离你的应用程序第一):

compile 'com.android.support:multidex:x.y.z'


Google Play服务
提供Google提供的各种服务和API,从Google地图到Android Pay,从穿戴式设备到广告。 它是从Google Play商店更新的,因此它的Android操作系统版本是独立的。 要包含在您的项目中:
compile 'com.google.android.gms:play-services:x.y.z'
如果你不想包括整个包(因为它是非常大,你可能会遇到超过65k的方法错误),你可以选择性地包括你想要使用的模块:
compile 'com.google.android.gms:play-services-wearable:x.y.z'
compile 'com.google.android.gms:play-services-maps:x.y.z'

...


Retrofit 2
当涉及到实现REST API时,Retrofit仍然是我最喜欢的库。 从他们的网站:“Retrofit将您的REST API变成Java接口。”这是一个优雅的解决方案,用于在项目中组织API调用。 请求方法和相对URL添加了注释,这使代码干净和简单。 使用注释,您可以轻松添加请求正文,操作网址或标题并添加查询参数。 要包括此库,请将其添加到您的build.gradle文件中:
compile 'com.squareup.retrofit2:retrofit:2.y.z' 
compile 'com.squareup.retrofit2:converter-gson:2.y.z' 

compile 'com.squareup.retrofit2:adapter-rxjava:2.y.z'


这里有一个简单的例子,如何使用Retrofit with RxJava:
public interface RestAPI{
@GET(BuildConfig.PATH_TO_MOVIES_SERVICE)
Observable<List<Movie>> loadMovies();
// Helper class that sets up new service
 class Factory {
     public static RestAPI create() {
          Retrofit retrofit = 
new Retrofit.Builder() 
           .baseUrl(BuildConfig.API_BASE_URL)
           .addConverterFactory(GsonConverterFactory.create())
           .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
           .build();                                                                                                                                                                                    
            
return retrofit.create(RestAPI.class);
  }
}


RxJava

是Reactive Extensions的Java VM实现,帮助您组合异步,基于事件,类似于代码的流和添加功能编程范例。 这是所有你需要包括这个库:
compile 'io.reactivex:rxjava:x.y.z'


RxAndroid

包装RxJava库。 它增加了Android特定线程的功能。 注意RxAndroid自动包括一个版本的RxJava。 但是,因为RxAndroid版本是在它后面,如果你想使用最新的RxJava,那么包括两个像:
compile 'io.reactivex:rxandroid:x.y.z'
compile 'io.reactivex:rxjava:x.y.z'
Let’s take an example:
private class SomeWebServiceTask extends  
AsyncTask <String,Result,Void> 
{


  protected Result doInBackground(String... someData) {
    Result result = webService.doSomething(someData);
    return result;
  }


  protected void onPostExecute(Result result) {
    if (result.isSuccess() {
      resultText.setText("Hello, world!");
    }
  }


}
或者
webService.doSomething(someData)
          .observeOn(AndroidSchedulers.mainThread())
          .subscribe( result -> resultText.setText("Hello, world!"),
                      e -> handleError(e));

是啊! 说再见AsyncTasks。


ButterKnife
在每个Android应用程序中,您必须对布局中的每个视图使用findViewById()方法,以便在应用程序的代码中使用。 但是随着应用程序设计的复杂布局,对这个方法的调用变得重复,这就是ButterKnife库所在。
这是所有你需要包括这个库:

compile 'com.jakewharton:butterknife:x.y.z'


让我们举个例子。 你最喜欢哪一个?
private TextView mFirstNameLabel;
private TextView mLastNameLabel;
private Button mSubmitButton;


@Override
protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  mFirstNameLabel = (TextView) findViewById(R.id.firstnameLabel);
  mLastNameLabel = (TextView) findViewById(R.id.lastnameLabel);
  mSubmitButton = (Button) findViewById(R.id.submitButton);
  mSubmitButton.setOnClickListener(new View.OnClickListener() {
             public void onClick(View v) {
                 //  TODO call ...
             }
         });
}
或者
@Bind(R.id.firstnameLabel) TextView mFirstNameLabel;
@Bind(R.id.lastnameLabel) TextView mLastNameLabel;
@OnClick(R.id.submitButton) void submit() {
    // TODO call ...
  }
@Override
protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_my);
  ButterKnife.bind(this);
}

第二个代码块使用库,它使用注释通过为您创建样板代码来“绑定”视图。 ButterKnife是小巧,简单,轻量级的,因为它使你的生活作为一个开发人员更容易,你应该几乎总是使用它。 这将是巨大的,如果Android SDK本身可以以这种方式改进!


Picasso / Glide
Picasso/Glide.  优秀和高效的图像加载库从网络和更多。 但是,在我看来,Glide是现在的最佳选择。 它包含在Google I / O 2014官方应用程序中。 这是所有你需要包括这个库:
/** Picasso **/
compile 'com.squareup.picasso:picasso:x.y.z'
/** Glide **/
compile 'com.github.bumptech.glide:glide:x.y.z'


这篇文章解释了Picasso Glide之间的区别。

这里有一个简单的例子,您可以使用Picasso将图像从URL加载到ImageView中:
@Bind(R.id.image_view) ImageView imageView;
Picasso.with(this).load(imageUrl).into(imageView);


这里有一个简单的例子,您可以使用Glide 将图像从URL加载到ImageView中:

@Bind(R.id.image_view) ImageView imageView;
Glide.with(this).load(imageUrl).into(imageView);


Timber

是一个轻量级库,可以在不同地方写入日志,并以集中的方式控制它的工作方式。 很容易将其添加为Android Studio项目的依赖项;
compile 'com.jakewharton.timber:timber:x.y.z'
典型的日志如下所示:
public static String TAG = "ClassName";
...
Log.e(TAG, “A message here”);
但是使用Timber,您可以在应用程序创建中使用类似以下代码:
@Override 
public void onCreate() {
    super.onCreate();
    if (BuildConfig.DEBUG) {
      Timber.plant(new DebugTree());
    } else {
      Timber.plant(new CrashReportingTree());
    }
}
/** 一个记录崩溃报告重要信息的树。
  
private static class CrashReportingTree extends Timber.HollowTree {
    @Override 
    public void i(String message, Object... args) {
      // TODO e.g., Crashlytics.log(String.format(message, args));
    }


    @Override 
    public void i(Throwable t, String message, Object... args) {
      i(message, args); // Just add to the log.
    }


    @Override 
    public void e(String message, Object... args) {
      i("ERROR: " + message, args); //Just add to the log.
    }


    @Override 
    public void e(Throwable t, String message, Object... args) {
      e(message, args);
      // TODO e.g., Crashlytics.logException(t);
    }
}
//

Timber.i("Message here");


Otto (事件总线)
是一个简化应用程序的不同部分之间的通信的库。 例如,将某个活动从某个活动发送到正在运行的服务,或者在片段之间轻松交互。 要包括它添加到您的gradle:
compile 'com.squareup:otto:x.y.z'
以下是我们使用的示例,如果Internet连接丢失,显示如何通知活动:
public class NetworkStateReceiver extends BroadcastReceiver {


  // 如果没有互联网连接,则发生事件
  public void onReceive(Context context, Intent intent) {
    super.onReceive(context, intent);
    if(intent.getExtras()!=null) {
     NetworkInfo ni=(NetworkInfo) intent.getExtras().get(ConnectivityManager.EXTRA_NETWORK_INFO);
      if(ni!=null && ni.getState()==NetworkInfo.State.CONNECTED) 
       {
                // there is Internet connection
       } 
      else if(intent.getBooleanExtra
         (ConnectivityManager.EXTRA_NO_CONNECTIVITY, Boolean.FALSE)) 
       {
         // no Internet connection,send network state changed
         Bus.post(newNetworkStateChanged(false));
       }
}


// 事件
public class NetworkStateChanged {


    private mIsInternetConnected;


    public NetworkStateChanged(boolean isInternetConnected) {
        this.mIsInternetConnected = isInternetConnected;
    }


    public boolean isInternetConnected() {
        return this.mIsInternetConnected;
    }
}


public class MainActivity extends Activity {    
 
   public static Bus bus;
     @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);


        bus = new Bus();
        bus.register(this); // register Otto event Bus
    }


    @Override
    protected void onDestroy() {
        super.onDestroy();
        bus.unregister(this); // unregister Otto event Bus
    }
//Method that will be called when someone posts an event NetworkStateChanged
    public void onEventMainThread(NetworkStateChanged event) {
        if (!event.isInternetConnected()) {
            Toast.makeText(this, "No Internet connection!", Toast.LENGTH_SHORT).show();
        }
    }


}

正如我先说,Otto(事件总线)允许你直接连接这些类。 你可以有一个事件从类A通知类B与唯一的中介本身。 但是在采用RxJava之后,我认为Rx和事件总线都使用反应模式,而RxJava则更好。 所以我们可以说再见事件总线。 这是一个RxJava作为事件总线的实现:

public class RxBus {
 
   private final Subject<Object, Object> bus = new   SerializedSubject<>(PublishSubject.create());
   public void post(Object o) {
     bus.onNext(o);
   }
   // Subscribe to this Observable. to get it 
   public Observable<Object> getEvents() {
     return bus;
   }
}
// Subscribe to the event 
getEvents().subscribe(new Action1<Object>() {
  @Override 
  public void call(Object o) {
    if(o instanceof AnswerEvent){
      // TODO
    }
  }

});


RetroLambda
这是一种使用Java 8 Lambdas到Java 6/7(以及Android)的方法。 使你的代码更清洁,结合它与RxJava和你是坚实的。 这是所有你需要包括它:
classpath 'me.tatarka:gradle-retrolambda:x.y.z'
apply plugin: 'me.tatarka.retrolambda'
下面是一个简单的例子如何使用Retrolambda & RxJava
Observable.just("Hello, world!")
          .subscribe(s -> System.out.println(s));

是啊! 清洁和简洁的代码。


Dagger 2
Dagger 2是著名的Dagger依赖注入库的继承者,我强烈推荐它。 其中一个主要的改进是在生成的注入代码中使用零反射,这使得调试更容易。
Dagger创建你的类的实例,并满足他们的依赖。 它依赖于javax.inject.Inject注释来标识哪些构造函数或字段应被视为依赖关系。 让我们来看看这个着名的CoffeeMaker示例:class Thermosiphon implements Pump {
  private final Heater heater;


  @Inject
  Thermosiphon(Heater heater) {
    this.heater = heater;
  }


  ...
}
An example with direct injection into fields:
class CoffeeMaker {
  @Inject Heater heater;
  @Inject Pump pump;


  ...
}
Dependencies are provided via modules and @Provides annotation from Dagger:
@Module
class DripCoffeeModule {
  @Provides 
  Heater provideHeater() {
    return new ElectricHeater();
  }


  @Provides 
  Pump providePump(Thermosiphon pump) {
    return pump;
  }
}
要使用它添加到build.gradle文件:
compile 'com.google.dagger:dagger:x.y.z'

compile 'org.glassfish:javax.annotation:10.0-b28'//annotation Dagger                         compile 'com.google.dagger:dagger-compiler:x.y.z'//Dagger compiler


Realm
是Android中的另一种类型的数据库。 但是,非常重要的是,Realm不使用SQLite。 如果使用ORMLite或ActiveAndroid或任何其他类似的库,您的数据存储在SQLite数据库中,因为这些库给我们在SQLite上只有一个覆盖。 与Realm它是完全不同的是没有SQLite。 这就是你需要使用它:classpath 'io.realm:realm-gradle-plugin:x.y.z'
//
apply plugin: 'realm-android'


这里有一个非常简单的例子如何使用它:
public class Book extends RealmObject {
 
    @Required
    private String title;
 
    public String getTitle() {
        return title;
    }
 
    public void setTitle(final String title) {
        this.title = title;
    }
}
// MAIN_ACTIVITY
public class MainActivity extends Activity {
private Realm mRealm;
 
 @Override
 public void onCreate(final Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   mRealm = Realm.getInstance(getContext());
 }
 @Override
 public void onDestroy() {
   super.onDestroy();
   mRealm.close();
 }
// Example of add/ remove a book
@OnClick(R.id.add)
public void onAddClick() {
  mRealm.beginTransaction();
  Book book = mRealm.createObject(Book.class);
  book.setTitle(getTrimTitle());
  mRealm.commitTransaction();
}
 
@OnClick(R.id.remove)
public void onRemoveClick() {
  mRealm.beginTransaction();
  RealmResults<MyBook> books = mRealm.where(Book.class)                     
                          .equalTo("title",getTrimTitle())
                          .findAll();
  if(!books.isEmpty()) {
    for(int i = books.size() - 1; i >= 0; i--) {
      books.get(i).removeFromRealm();
    }
  }
    mRealm.commitTransaction();
}
 
 private String getTrimTitle() {
    return mEditTitle.getText().toString().trim();
 }

}


ViewPropertyAnimator
ViewPropertyAnimator在API级别12引入,允许您使用单个Animator实例简单高效地对多个视图属性执行动画操作(并行)。 对我们来说实现程序化是简单和整洁的:
// Animate Button
mButton.animate()        
       .alpha(1f)        
       .scaleX(1f)       
       .scaleY(1f)        
       .translationZ(10f)        
       .setInterpolator(new FastOutSlowInInterpolator())                        
       .setStartDelay(200)        
       .setListener(new Animator.AnimatorListener() {            
          @Override           
          public void onAnimationStart(Animator animation) { }                     
          @Override   
          public void onAnimationEnd(Animator animation) { }              
          @Override            
          public void onAnimationCancel(Animator animation) { }             
          @Override            
          public void onAnimationRepeat(Animator animation) { }        
        })
       .start();
转换框架
Android转换框架允许您配置应用程序用户界面中的更改的外观。 它提供工具,以有效地管理和导航生活的过渡。 这个框架有一些限制:
应用于SurfaceView的动画可能无法正确显示。 SurfaceView实例从非UI线程更新,因此更新可能与其他视图的动画不同步。
一些特定的过渡类型在应用于TextureView时可能不会产生所需的动画效果。
扩展AdapterView的类(如ListView)以与转换框架不兼容的方式管理其子视图。 如果尝试对基于AdapterView的视图进行动画处理,则设备显示可能会挂起。
如果您尝试使用动画调整TextView的大小,则在对象完全调整大小之前,文本将会弹出到新位置。 要避免此问题,请不要对包含文本的视图的大小调整进行动画处理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值