玩轉OneNET物聯網平臺之MQTT服務⑤ —— OneNet智能燈+MVP框架

授人以魚不如授人以漁,目的不是爲了教會你具體項目開發,而是學會學習的能力。但願你們分享給你周邊須要的朋友或者同窗,說不定大神成長之路有博哥的奠定石。。。web

QQ技術互動交流羣:ESP8266&32 物聯網開發 羣號622368884,不喜勿噴數據庫

1、你若是想學基於Arduino的ESP8266開發技術

1、基礎篇服務器

  1. ESP8266開發之旅 基礎篇① 走進ESP8266的世界
  2. ESP8266開發之旅 基礎篇② 如何安裝ESP8266的Arduino開發環境
  3. ESP8266開發之旅 基礎篇③ ESP8266與Arduino的開發說明
  4. ESP8266開發之旅 基礎篇④ ESP8266與EEPROM
  5. ESP8266開發之旅 基礎篇⑤ ESP8266 SPI通訊和I2C通訊
  6. ESP8266開發之旅 基礎篇⑥ Ticker——ESP8266定時庫

2、網絡篇網絡

  1. ESP8266開發之旅 網絡篇① 認識一下Arduino Core For ESP8266
  2. ESP8266開發之旅 網絡篇② ESP8266 工做模式與ESP8266WiFi庫
  3. ESP8266開發之旅 網絡篇③ Soft-AP——ESP8266WiFiAP庫的使用
  4. ESP8266開發之旅 網絡篇④ Station——ESP8266WiFiSTA庫的使用
  5. ESP8266開發之旅 網絡篇⑤ Scan WiFi——ESP8266WiFiScan庫的使用
  6. ESP8266開發之旅 網絡篇⑥ ESP8266WiFiGeneric——基礎庫
  7. ESP8266開發之旅 網絡篇⑦ TCP Server & TCP Client
  8. ESP8266開發之旅 網絡篇⑧ SmartConfig——一鍵配網
  9. ESP8266開發之旅 網絡篇⑨ HttpClient——ESP8266HTTPClient庫的使用
  10. ESP8266開發之旅 網絡篇⑩ UDP服務
  11. ESP8266開發之旅 網絡篇⑪ WebServer——ESP8266WebServer庫的使用
  12. ESP8266開發之旅 網絡篇⑫ 域名服務——ESP8266mDNS庫
  13. ESP8266開發之旅 網絡篇⑬ SPIFFS——ESP8266 Flash文件系統
  14. ESP8266開發之旅 網絡篇⑭ web配網
  15. ESP8266開發之旅 網絡篇⑮ 真正的域名服務——DNSServer
  16. ESP8266開發之旅 網絡篇⑯ 無線更新——OTA固件更新

3、應用篇架構

  1. ESP8266開發之旅 應用篇① 局域網應用 ——炫酷RGB彩燈
  2. ESP8266開發之旅 應用篇② OLED顯示天氣屏
  3. ESP8266開發之旅 應用篇③ 簡易版WiFi小車

4、高級篇app

  1. ESP8266開發之旅 進階篇① 代碼優化 —— ESP8266內存管理
  2. ESP8266開發之旅 進階篇② 閒聊Arduino IDE For ESP8266配置
  3. ESP8266開發之旅 進階篇③ 閒聊 ESP8266 Flash
  4. ESP8266開發之旅 進階篇④ 常見問題 —— 解決困擾
  5. ESP8266開發之旅 進階篇⑤ 代碼規範 —— 像寫文章同樣優美
  6. ESP8266開發之旅 進階篇⑥ ESP-specific APIs說明

1.前言

    在上一篇博文 玩轉OneNET物聯網平臺之MQTT服務④ —— 遠程控制LED(設備自注冊)+ Android App控制 中,博主提供了OneNet智能燈的Mqtt協議的配套App。那麼,爲了方便你們開發以及拓展,博主這裏簡述一下源碼設計。框架

2.源碼下載

  • 請到博主技術交流羣羣文件下載:
    在這裏插入圖片描述

3.源碼分析

3.1 App開發工具

  • Android Studio,官方認證工具,請自行配置好Java環境以及AS工具,目前博主屬於最新版本。

3.2 代碼總體結構

  • 把上面下載下來的源碼導入Android Studio以後,能夠看到以下結構:
    在這裏插入圖片描述
    博主這裏爲了開發方便,分出了三個module:
  • app_common,經常使用公共模塊,好比各類工具類(打印日誌工具,時間格式轉換工具)
    在這裏插入圖片描述
  • app_ormlib,數據庫服務(這裏沒有用到,爲了後面拓展預留)
    在這裏插入圖片描述
  • app_widget,經常使用UI,基礎組件,包括封裝基礎activity類,recyclerview,以及我普遍應用的mvp設計框架
    在這裏插入圖片描述
  • app:這裏就是咱們主要的業務代碼。
    在這裏插入圖片描述

3.3 MVP框架解析

  • 至於什麼叫作MVP,博主這裏不講,請自行百度。如下代碼構成了MVP的主體框架:
    在這裏插入圖片描述
    Model:專一於處理數據
    View:專一於頁面顯示
    Presenter:協調Model和View的調用關係
  • 接下來,看基於MVP架構的業務代碼:
    在這裏插入圖片描述
    經過名字就能夠快速知道對應的具體業務:
  • 配置MQTT頁面:OneNetConfigXXXX
  • 列表主頁面:MainXXXXX
  • 關於應用頁面:AboutMeXXXX
  • 拓展頁面:XXXXXXX

接下來,咱們挑一個頁面來說解,方便你們瞭解MVP工做方式。ide

3.4 Main控制主頁面解析

3.4.1 MVP協議

/**
 * mvp 主頁面協議 presenter層
 */
public interface IMainContract {
    // model層
    interface IMainModel extends IBaseModel {
        void loadData(Context context, ICallBack<List<OneNetDeviceModel>> callBack);
        void updateDeviceDetail(Context context,OneNetDeviceModel model, ICallBack<String> callBack);
    }
    //view層
    interface IMainView extends IBaseView {
        void showLoading(String loadmsg);
        void dismissLoading(OnDismissCallbackListener callback);
        void refreshList(List<OneNetDeviceModel> list);
    }
}

3.4.2 Model層-數據處理

  • 咱們關注Main相關的代碼:
public class MainModel implements IMainContract.IMainModel {

    SimpleTask task;
    //獲取設備列表
    @Override
    public void loadData(Context context, final ICallBack<List<OneNetDeviceModel>> callBack) {

        if(task != null && task.getStatus()== AsyncTask.Status.RUNNING){
            task.cancel(true);
        }
        task = new SimpleTask() {

            GetOneNetDeviceListEntity entity;

            @Override
            protected void onPreExecute() {
                entity = new GetOneNetDeviceListEntity();
            }

            @Override
            protected Object doInBackground(String... strings) {
                return entity.request();
            }

            @Override
            protected void onPostExecute(Object o) {
                String result = (String) o;
                if("200".equals(result)){
                   if(entity.data != null && entity.data.devices.size()!=0) {
                       List<OneNetDeviceModel> list = new ArrayList<>();
                       for(OneNetDeviceModel model:entity.data.devices){
                           if(!model.getId().equals(PreferenceUtil.getInstance().getDeviceId())){
                               list.add(model);
                           }
                       }

                       callBack.onSuccess(list);
                   }
                }else {
                    callBack.onFaild(result);
                }
            }
        };
        task.startTask();
    }

//更新設備信息
    @Override
    public void updateDeviceDetail(Context context, final OneNetDeviceModel model, final ICallBack<String> callBack) {
        if(task != null && task.getStatus()== AsyncTask.Status.RUNNING){
            task.cancel(true);
        }
        task = new SimpleTask() {

            UpdateOneNetDeviceDetailEntity entity;

            @Override
            protected void onPreExecute() {
                entity = new UpdateOneNetDeviceDetailEntity(model.getId());
            }

            @Override
            protected Object doInBackground(String... strings) {
                return entity.request(model);
            }

            @Override
            protected void onPostExecute(Object o) {
                String result = (String) o;
                if("200".equals(result)){
                    callBack.onSuccess("更新成功");
                }else {
                    callBack.onFaild(result);
                }
            }
        };
        task.startTask();
    }
}

3.4.3 View層-UI處理

/**
 * @author wty
 * @Description 控制頁面
 **/
public class MainActivity extends BaseActivity<MainPresenter> implements IMainContract.IMainView {

    @Bind(R.id.listview)
    XRecyclerView listview;

    DeviceListAdapter adapter;


    public static void startActivity(Activity activity) {
        Intent intent = new Intent(activity, MainActivity.class);
        activity.startActivity(intent);
    }

    @Override
    public MainPresenter getPresenter() {
        return new MainPresenter();
    }

    @Override
    public void onInitView(Bundle savedInstanceState) {
        /**
         * 第一個參數是服務器地址
         * 第二個參數是用戶名
         * 第三個參數是密碼
         * 第四個參數是客戶端ID
         * 第五個參數是主題
         **/
        MqttManager
                .getInstance()
                .creatConnect(
                        AppConstant.RequestUrl.ONENET_MQTT,
                        PreferenceUtil.getInstance().getProductId(),
                        PreferenceUtil.getInstance().getApiKey(),
                        PreferenceUtil.getInstance().getDeviceId(),
                        "esp8266");

        getDefaultNavigation().setTitle("OneNet智能燈");
        getDefaultNavigation().getLeftButton().setButton("配置", new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                OneNetMqttConfigActivity.startActivity(MainActivity.this);
                finish();
            }
        });
        getDefaultNavigation().getRightButton().setButton("關於應用", new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                AboutActivity.startActivity(MainActivity.this);
            }
        });

        LinearLayoutManager layoutManager = new LinearLayoutManager(this);
        layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
        listview.setLayoutManager(layoutManager);
        listview.setPullRefreshEnabled(false);
        listview.setLoadingMoreEnabled(false);
        List<OneNetDeviceModel> data = new ArrayList<>();
        adapter = new DeviceListAdapter(this,data,mPresenter);
        listview.setAdapter(adapter);

        mPresenter.refreshList(MainActivity.this);
    }

    @Override
    protected boolean isEnableStatusBar() {
        return true;
    }

    @Override
    protected List<String> validate() {
        List<String> list = super.validate();
        return list;
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        MqttManager.release();
    }

    @Override
    public int getLayoutResource() {
        return R.layout.activity_main;
    }

    @Override
    public void refreshList(List<OneNetDeviceModel> list) {
        adapter.retsetData(list);
    }
}

3.4.4 Presenter層-中間協調層

/**
 * 主頁面 presenter
 */
public class MainPresenter extends BasePresenter<IMainContract.IMainView> {

    private IMainContract.IMainModel mMainModel;

    public MainPresenter(){
        mMainModel = new MainModel();
    }

    public void refreshList(Context context){
        mView.showLoading("獲取設備列表中...");

        mMainModel.loadData(context, new ICallBack<List<OneNetDeviceModel>>() {
            @Override
            public void onSuccess(final List<OneNetDeviceModel> list) {
                mView.refreshList(list);
                mView.dismissLoading();
            }

            @Override
            public void onFaild(String msg) {
                mView.dismissLoading(new OnDismissCallbackListener(msg, SweetAlertDialog.ERROR_TYPE));
            }
        });
    }

    public void updateDeviceDetail(final Context context, OneNetDeviceModel model){
        mView.showLoading("更新設備信息中...");

        mMainModel.updateDeviceDetail(context,model, new ICallBack<String>() {
            @Override
            public void onSuccess(final String result) {
                mView.dismissLoading();
                refreshList(context);
            }

            @Override
            public void onFaild(String msg) {
                mView.dismissLoading(new OnDismissCallbackListener(msg, SweetAlertDialog.ERROR_TYPE));
            }
        });
    }
}

基本上,每一個頁面都是按照這個MVP的設計思路去分析就能夠了,很是簡單。工具

4.總結

一句話,高手勿噴。源碼分析

相關文章
相關標籤/搜索