安卓开发逐步走向标准化,规范化,一个合格的安卓程序员,应该要有代码强迫症,哪些臃肿的代码结构,需要想方设法去优化改变,我本菜鸟,只能一步步去远离菜鸟,我非大神,只能一步步模仿大神
目前流行的开发模式,以我目前的所能接触到的知识面,在我眼中应该是
MVP(因此安卓中这个说的比较多)
注解(Android Annotations、ButterKnife我一般不用,我还是喜欢findViewById)
异步框架(Rxjava最近说的比较多)
混合开发(原生,混合谁也取代不了谁,各取所长)
Retrofit(网络单拎出来)
。。。
。。。
未来还会有更好的
在了解今天的小框架学习中,你可以先去了解了解其他的内容
Volley、OkHttp、Retrofit+Rxjava总结
今天我们就来简单的了解下,如何搭建一个简单的mvp小项目框架
本博文代码,免积分下载!!!免积分下载!!!
我们的需求很简单,看如下截图即可
需求是:点击从上到下的第二个Button控件,在第一个TextView控件上显示App版本号
首先看我们需要依赖的东东
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:23.4.0'
compile 'com.android.support:support-v4:23.4.0'
compile 'com.squareup.retrofit2:retrofit:2.1.0'
compile 'com.google.code.gson:gson:2.6.2'
compile 'com.squareup.retrofit2:converter-gson:2.0.0-beta4'
compile 'io.reactivex:rxjava:1.1.6'
compile 'io.reactivex:rxandroid:1.2.1'
compile 'com.squareup.retrofit2:adapter-rxjava:2.0.2'
}
我这个小例子还得需要,我用的是jdk1.7的,不知道1.8的是不是就没有这个问题
multiDexEnabled true
什么是MVP?
M就是model数据层,就是承载数据的实体
V就是view界面层,就是展示数据的
P就是Presenter(百度翻译为提出者; 赠送者)就是从Model中获取数据并提供给View的层
需求是:点击从上到下的第二个Button控件,在第一个TextView控件上显示App版本号
牛逼的程序员,都是设计模式、泛型、接口用的很溜的,我们也试着尽可能的模仿牛人的代码
我们该如何去层层剥离代码呢?
MVP其实没有想的那么高端,最简单的MVP的思路就是
就拿我们这个例子来说,V层就是去获取P层提供的数据(我们这里就是获取一个VersionCode),在调用自己的方法,去显示即可
先拿View层来说把:
首先View层自身得有一个方法,去展现获取到的VersionCode,其实在一个APP中,可以根据业务逻辑,抽取共同的View层方法,本例就不抽取了 ,但是预留了一个空接口,ok,那么我们就先看看View层的最最基本的接口对象
BaseView
package com.safly.base;
public interface BaseView {
}
好吧,那么继续我们就来构造本例中的View层MainViewImpl
package com.safly.ui.inner;
import com.safly.base.BaseView;
public interface MainViewImpl extends BaseView {
void setAppVersion(int appVersion);
}
MainViewImpl很简单嘛,就是接收一个P层获取的数据的传入,然后在展现界面即可
最后的View层是MainActivity这里先不说,先来分析下P层
P层同样是一样的,需要获取AppVersionCode供给View层使用
MainPresenterImpl
package com.safly.presenter.inter;
public interface MainPresenterImpl {
public void getAppVersion();
}
至此V层P层最基本的方法就构造完毕了,接下来就去完事如何将V层P层,进行连接起来
还拿我们这个例子说,点击Button,就去调用P层的getAppVersion方法,获取数据完毕,就调用V层的setAppVersion方法,所以说P层得需要持有V层的引用,这是必须要做的事
BasePresenter
package com.safly.base;
public class BasePresenter<V extends BaseView>{
public V view;
public void bindView(V view){
this.view = view;
}
public void unBindView(){
this.view = null;
}
public boolean checkBindView(){
return view == null;
}
}
由于一个app是有好多View界面的,所以我们不能去写更多的P层,我们需要抽取一个基类,这就是引入了泛型 V extends BaseView
那么接下来我们就去看看最后的P是如何写的MainPresenter
package com.safly.presenter;
import android.content.Context;
import com.safly.base.BasePresenter;
import com.safly.presenter.inter.MainPresenterImpl;
import com.safly.ui.inner.MainViewImpl;
import com.safly.utils.AppUtils;
public class MainPresenter extends BasePresenter<MainViewImpl> implements MainPresenterImpl{
Context mContext;
public MainPresenter(Context mContext) {
this.mContext = mContext;
}
@Override
public void getAppVersion() {
int versionCode = AppUtils.getVersionCode(mContext);
view.setAppVersion(versionCode);
}
}
MainPresenter 持有View层的引用,P调用getAppVersion,然后V层setAppVersion方法即可
在看MainActivity之前我们需要对View层做进一步的抽取,我先贴出代码,然后在做简单分析
BaseActivity
package com.safly.base;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.LayoutInflater;
import java.util.zip.Inflater;
/**
* Created by safly on 2016/11/9.
*/
public abstract class BaseActivity<V extends BaseView,P extends BasePresenter<V>> extends AppCompatActivity {
public LayoutInflater mInflater;
public P presenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(getLayouResId());
mInflater = LayoutInflater.from(this);
presenter = initPresenter();
presenter.bindView((V)this);
initRes();
doOtherWork();
}
@Override
protected void onResume() {
super.onResume();
doOnResume();
}
protected abstract void doOnResume();
protected abstract void doOtherWork();
protected abstract P initPresenter();
public abstract int getLayouResId();
protected abstract void initRes();
@Override
protected void onDestroy() {
super.onDestroy();
if (presenter != null){
presenter.unBindView();
}
}
}
在上面代码中initPresenter是持有P层的引用,为了去构造不同的View层的P类对象,
presenter.bindView((V)this);是P层绑定V层,便于V层调用本类方法
getLayouResId、initRes、doOtherWork、doOnResume这些就是大家比较熟悉的了,获取布局文件、初始化控件、获取数据操作,onResume等等,你也可以根据项目需要进行进一步扩充
千呼万唤使出来,最后看MainActivity本例的V层
package com.safly.ui;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import com.safly.R;
import com.safly.base.BaseActivity;
import com.safly.presenter.MainPresenter;
import com.safly.ui.inner.MainViewImpl;
import java.util.concurrent.TimeUnit;
import rx.Subscriber;
import rx.functions.Action1;
public class MainActivity extends BaseActivity<MainViewImpl,MainPresenter> implements View.OnClickListener,MainViewImpl{
TextView showAppVersion;
Button showToast;
@Override
public int getLayouResId() {
return R.layout.activity_main;
}
@Override
protected void initRes() {
showAppVersion = (TextView) findViewById(R.id.showAppVersionCode);
showToast = (Button) findViewById(R.id.showToast);
showToast.setOnClickListener(this);
}
@Override
protected MainPresenter initPresenter() {
return new MainPresenter(this);
}
@Override
protected void doOtherWork() {
}
@Override
protected void doOnResume() {
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.showToast:
presenter.getAppVersion();
break;
}
}
@Override
public void setAppVersion(final int appVersion) {
rx.Observable.create(new rx.Observable.OnSubscribe<Integer>() {
@Override
public void call(Subscriber<? super Integer> subscriber) {
subscriber.onNext(appVersion);
}
}).subscribe(new Action1<Integer>() {
@Override
public void call(Integer integer) {
showAppVersion.setText(String.valueOf(integer));
}
});
}
private boolean hasClickBack = false;
@Override
public void onBackPressed() {
if (hasClickBack) {
this.finish();
} else {
hasClickBack = true;
Toast.makeText(this, "再次按退出Demo", Toast.LENGTH_SHORT).show();
rx.Observable.create(new rx.Observable.OnSubscribe<Boolean>() {
@Override
public void call(Subscriber<? super Boolean> subscriber) {
subscriber.onNext(false);
}
}).delay(3, TimeUnit.SECONDS)
.subscribe(new Action1<Boolean>() {
@Override
public void call(Boolean aBoolean) {
hasClickBack = aBoolean.booleanValue();
}
});
}
}
}
现在MainActivity中代码就显得很清晰了,解析来我们就看看Rxjava的简单使用,这里只是简单使用而已
@Override
public void setAppVersion(final int appVersion) {
rx.Observable.create(new rx.Observable.OnSubscribe<Integer>() {
@Override
public void call(Subscriber<? super Integer> subscriber) {
subscriber.onNext(appVersion);
}
}).subscribe(new Action1<Integer>() {
@Override
public void call(Integer integer) {
showAppVersion.setText(String.valueOf(integer));
}
});
}
private boolean hasClickBack = false;
@Override
public void onBackPressed() {
if (hasClickBack) {
this.finish();
} else {
hasClickBack = true;
Toast.makeText(this, "再次按退出Demo", Toast.LENGTH_SHORT).show();
rx.Observable.create(new rx.Observable.OnSubscribe<Boolean>() {
@Override
public void call(Subscriber<? super Boolean> subscriber) {
subscriber.onNext(false);
}
}).delay(3, TimeUnit.SECONDS)
.subscribe(new Action1<Boolean>() {
@Override
public void call(Boolean aBoolean) {
hasClickBack = aBoolean.booleanValue();
}
});
}
}
第一个是获取AppVersionCode,然后在View界面上设置数据
第二个是3秒内连续点击会退键退出Demo
我对Rxjava也是简单了解而已,如果你也想着简单了解可以去看看博客开头的几篇博文,Retrofit里面有对Rxjava的封装,还有一篇专门讲Rxjava的
最后SaflyApplication获取全局变量的
package com.safly;
import android.app.Application;
public class SaflyApplication extends Application {
private static SaflyApplication instance;
@Override
public void onCreate() {
super.onCreate();
SaflyApplication.instance = this;
}
public static SaflyApplication getInstance(){
return SaflyApplication.instance;
}
}
以上就是一个简单的MVP的小架子,自己的思路,有好建议,请指出,多谢!!!