Android APP架构的那点事儿[MVP架构搭建]

接上篇《APP架构的那点事儿[网络模块]》

完成了网络模块,那么我们是不是该进入MVP主体架构的开发了,当然,有些朋友会说:“难道一定要先写网络模块,就不能先做架构主体么!” 这个随意了,看个人喜好,有话好好说嘛,把砖头放下.

MVP结构图

所谓的mvp,个人理解为model层处理业务逻辑(主要是数据读写、与服务器端通信(其实也是读写数据));view层处理ui显示(通常包含Activity、Fragment、View (应该如何选择));presenter层为指示器,应该说包含很多个Presenter组成,作为中间件操作相对应的model和view)

具体MVP细节,感兴趣的朋友搜下,很多!

如何下手开发?其实我们可以从一个简单的功能点入手,然后其他功能照着模子继续造轮子就行。下面简单一个获取城市列表的例子。

这里写图片描述

Model层
/**
 * 城市对象模型
 * Created by liaonaibo on 16/2/14.
 */
public class City extends BaseResource{
    /**城市ID*/
    public int id;
    /**省份名称*/
    public String province;
    /**城市*/
    public String city;
    /**城市/区名称*/
    public String district;

    public City(){
        this.dataType = DataType.DT_List_City_Weather;
    }

    public static List<City> parserList(String json){
        try {
            JSONObject obj = new JSONObject(json);
            String data = obj.optString("result");
            if (!TextUtils.isEmpty(data)) {
                List<City> list = new Gson().fromJson(data,
                        new TypeToken<List<City>>() {
                        }.getType());
                return list;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}
Presenter层
/**
 * 城市列表UI主持者
 * 作为View与Model交互的中间纽带,处理与用户交互的负责逻辑
 * Created by liaonaibo on 16/2/15.
 */
public class CityListPresenter {
    private Context mContext;
    private ICityListView mICityListView;
    private boolean isLoading;
    private List<BaseResource> mData;
    public CityListPresenter(Context context,ICityListView iCityListView){
        this.mContext = context;
        this.mICityListView = iCityListView;
        this.mData = new ArrayList<BaseResource>();
    }

    public void getData(){
        if (isLoading){
            return;
        }
        isLoading = true;
        //通知UI数据加载中
        mICityListView.onDataLoading();
        NetworkController.getInstance(mContext).requestCityList(null, new NetworkRequestListener() {
            @Override
            public void response(String response) {
                isLoading = false;

                if(!TextUtils.isEmpty(response)){
                    List<City> list = City.parserList(response);
                    if(null != list && list.size() > 0){
                        mData.addAll(list);
                        //显示数据到UI上
                        mICityListView.showCityList(mData);
                    }else{
                        //没有数据了
                        mICityListView.requestDataFailByNoData();
                    }
                }

            }

            @Override
            public void error(int errorCode, String errorLog) {
                isLoading = false;
                //通知UI网络异常
                mICityListView.requestDataFailByNetswork();
            }
        });
    }

    /**
     * 跳转到天气详情界面
     * @param view
     */
    public void jumpToWeatherDetailActivity(View view) {
        Object object = view.getTag();

        if(null != object){
            City city = (City) object;
            WeatherDetailActivity.start(mContext, city);
        }
    }

    /**
     * 获取点击事件数组
     * @return
     */
    public View.OnClickListener[] getOnClickListeners() {
        View.OnClickListener[]  listeners = new View.OnClickListener[1];
        listeners[0] = new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                jumpToWeatherDetailActivity(v);
            }
        };
        return listeners;
    }

    /**
     * 搜索城市
     * @param cityName
     */
    public void searchCity(String cityName) {
        City city = new City();
        city.dataType = DataType.DT_List_City_Search;
        city.city = cityName;
        WeatherDetailActivity.start(mContext, city);
    }
}
View层

个人总结,对于View所需定义的接口,可以通过产品功能上的入手,熟悉产品交互流程, 然后考虑:

该操作需要什么?(那些参数?)
该操作的结果,对应的反馈?(显示列表??showFailedError?)
该操作过程中对应的友好的交互?(加载中?加载完成?)
/**
 * 城市列表View接口
 * Created by liaonaibo on 16/2/15.
 */
public interface ICityListView {
    /**显示城市列表*/
    void showCityList(List<BaseResource> list);
    /**数据加载中*/
    void onDataLoading();
    /**没有数据*/
    void requestDataFailByNoData();
    /**请求失败*/
    void requestDataFailByNetswork();
}
/**
 * 城市列表界面
 */
public class MainActivity extends FragmentActivity implements ICityListView, View.OnClickListener {

    private CityAdapter mAdapter;
    private ListView mListView;
    private ProgressBar mProgressBar;
    private EditText et_search;
    private CityListPresenter mPresenter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initVariable();
        initLayout();
        loadData();
    }

    /**
     * 初始化变量
     */
    private void initVariable() {
        mPresenter = new CityListPresenter(this, this);
    }

    /**
     * 初始化布局
     */
    private void initLayout() {
        mListView = (ListView) findViewById(R.id.activity_main_lv);
        mProgressBar = (ProgressBar) findViewById(R.id.activity_main_pb);
        et_search = (EditText) findViewById(R.id.activity_main_et_search);

        et_search.setOnEditorActionListener(new TextView.OnEditorActionListener() {
            public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
                if (actionId == EditorInfo.IME_ACTION_SEARCH || (event != null && event.getKeyCode() == KeyEvent.KEYCODE_ENTER)) {
                    searchCity();
                    return true;
                }
                return false;
            }
        });

        findViewById(R.id.activity_main_iv_search).setOnClickListener(this);
    }

    /**
     * 加载数据
     */
    private void loadData() {
        //调用主持者获取数据
        mPresenter.getData();
    }

    @Override
    public void showCityList(List<BaseResource> list) {
        mProgressBar.setVisibility(View.GONE);
        if (null == mAdapter) {
            mAdapter = new CityAdapter(this, mPresenter, list);
            mListView.setAdapter(mAdapter);
        } else {
            mAdapter.notifyDataSetChanged();
        }
    }

    @Override
    public void onDataLoading() {
        //TODO:数据加载中
        mProgressBar.setVisibility(View.VISIBLE);
    }

    @Override
    public void requestDataFailByNoData() {
        //TODO:没有数据了
        mProgressBar.setVisibility(View.GONE);
        Toast.makeText(this, "没有数据了,稍候重试", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void requestDataFailByNetswork() {
        //网络异常
        mProgressBar.setVisibility(View.GONE);
        Toast.makeText(this, "网络异常,稍候重试", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onClick(View v) {
        int id = v.getId();
        if (R.id.activity_main_iv_search == id) {
            searchCity();
        }
    }

    private void searchCity() {
        String city = et_search.getText().toString();
        if (TextUtils.isEmpty(city)) {
            Toast.makeText(this, "请输入城市名称", Toast.LENGTH_SHORT).show();
            return;
        }
        mPresenter.searchCity(city);
    }
}
如何选择使用Activity、Fragment、View?

有朋友问,项目应该使用Activity还是Fragment还是View?首先我们要理解这三者的关系

Activity、fragment、view三者关系

解释一下,Fragment的英译是”碎片”,Fragment是Activity的封装部件,简单说Fragment要基于Activity才能显示,View也一样。当Activity太大,承载太多不同功能或类型的UI的时候,可以尝试拆分为独立的多个独立的Fragment(或View)来显示UI。而Activity和Fragment是有生命周期的结构使用两者,保持职责清晰,心里要有个概念,那就是单一原则。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值