玩轉OneNET物聯網平台之MQTT服務⑤ —— OneNet智慧燈+MVP框架
- 2019 年 10 月 29 日
- 筆記
授人以魚不如授人以漁,目的不是為了教會你具體項目開發,而是學會學習的能力。希望大家分享給你周邊需要的朋友或者同學,說不定大神成長之路有博哥的奠基石。。。
QQ技術互動交流群:ESP8266&32 物聯網開發 群號622368884,不喜勿噴
一、你如果想學基於Arduino的ESP8266開發技術
一、基礎篇
二、網路篇
- ESP8266開發之旅 網路篇① 認識一下Arduino Core For ESP8266
- ESP8266開發之旅 網路篇② ESP8266 工作模式與ESP8266WiFi庫
- ESP8266開發之旅 網路篇③ Soft-AP——ESP8266WiFiAP庫的使用
- ESP8266開發之旅 網路篇④ Station——ESP8266WiFiSTA庫的使用
- ESP8266開發之旅 網路篇⑤ Scan WiFi——ESP8266WiFiScan庫的使用
- ESP8266開發之旅 網路篇⑥ ESP8266WiFiGeneric——基礎庫
- ESP8266開發之旅 網路篇⑦ TCP Server & TCP Client
- ESP8266開發之旅 網路篇⑧ SmartConfig——一鍵配網
- ESP8266開發之旅 網路篇⑨ HttpClient——ESP8266HTTPClient庫的使用
- ESP8266開發之旅 網路篇⑩ UDP服務
- ESP8266開發之旅 網路篇⑪ WebServer——ESP8266WebServer庫的使用
- ESP8266開發之旅 網路篇⑫ 域名服務——ESP8266mDNS庫
- ESP8266開發之旅 網路篇⑬ SPIFFS——ESP8266 Flash文件系統
- ESP8266開發之旅 網路篇⑭ web配網
- ESP8266開發之旅 網路篇⑮ 真正的域名服務——DNSServer
- ESP8266開發之旅 網路篇⑯ 無線更新——OTA韌體更新
三、應用篇
四、高級篇
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工作方式。
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.總結
一句話,高手勿噴。