玩轉OneNET物聯網平臺之MQTT服務⑤ —— OneNet智慧燈+MVP框架
阿新 • • 發佈:2019-10-29
授人以魚不如授人以漁,目的不是為了教會你具體專案開發,而是學會學習的能力。希望大家分享給你周邊需要的朋友或者同學,說不定大神成長之路有博哥的奠基石。。。
QQ技術互動交流群:ESP8266&32 物聯網開發 群號622368884,不喜勿噴
一、你如果想學基於Arduino的ESP8266開發技術
一、基礎篇
- ESP8266開發之旅 基礎篇① 走進ESP8266的世界
- ESP8266開發之旅 基礎篇② 如何安裝ESP8266的Arduino開發環境
- ESP8266開發之旅 基礎篇③ ESP8266與Arduino的開發說明
- ESP8266開發之旅 基礎篇④ ESP8266與EEPROM
- ESP8266開發之旅 基礎篇⑤ ESP8266 SPI通訊和I2C通訊
- ESP8266開發之旅 基礎篇⑥ Ticker——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韌體更新
三、應用篇
- ESP8266開發之旅 應用篇① 區域網應用 ——炫酷RGB彩燈
- ESP8266開發之旅 應用篇② OLED顯示天氣屏
- ESP8266開發之旅 應用篇③ 簡易版WiFi小車
四、高階篇
- ESP8266開發之旅 進階篇① 程式碼優化 —— ESP8266記憶體管理
- ESP8266開發之旅 進階篇② 閒聊Arduino IDE For ESP8266配置
- ESP8266開發之旅 進階篇③ 閒聊 ESP8266 Flash
- ESP8266開發之旅 進階篇④ 常見問題 —— 解決困擾
- ESP8266開發之旅 進階篇⑤ 程式碼規範 —— 像寫文章一樣優美
- 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工作方式。
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.總結
一句話,高手勿噴