編輯:關於Android編程
首先自問自答:
首先要知道為什麼要選擇開發框架?目的如下:
代碼可讀維護性好方便測試 框架的核心思想:解耦 分層:縱向上的解耦模塊化:橫向上的解耦橫向的模塊化:對大家來可能並不陌生,在一個項目建立項目文件夾的時候就會遇到這個問題,通常的做法是將相同功能的模塊放到同一個目錄下,更復雜的,可以通過插件化來實現功能的分離與加載。縱向的分層,不同的項目可能就有不同的分法,並且隨著項目的復雜度變大,層次可能越來越多
根據自己具體項目而定,如果業務簡單的項目,用MVC模式就可以了,不管是什麼開發框架,都是為了更好的提高工作效率,是手段,方法,不是目的,不要為了設計而設計,否則浪費時間,精力,得不償失。
為什麼要思考這問題?因為時間短暫,想要做的事情很多,必須學會取捨,才能更好的做好事情。
我有個原則:
最重要的事情,只有一件,要麼不做,要麼就做得最好
好處:
可以做其他,自己認為更重要的事情
壞處:
思維方面:對於一些基於MVP模式優秀項目,但是看不懂啊,閱讀大神優秀思想的作品,
無法享受思維上的樂趣,怎麼能阻礙我們成為大神的前進道路呢?不可原諒,beat it !
工作方面:如果項目業務很復雜,使用MVC模式,項目開發效率,管理,代碼可讀性低,測試和維護時間長,工作效率低
所以從否定角度,證明學習MVP模式是重要,是必須的,於是花時間,專門學習,研究MVP模式,運用到工作項目中,提高工作效率
1)如何認識MVP模式?(觀察現象)
回顧MVC模式
比較MVC模式和MVP模式的區別,通過比較區別,顯出MVP模式的特點,優勢
2)如何使用MVP模式?(使用方法)
通過例子分析
MVC之間的數據是如何流動的?
首先View控件設置監聽事件,在哪裡設置呢?可以在Controller中進行設置,比如在Activity中設置按鈕的點擊事件,也可以在自定義控件中進行設置,比如在Listview中設置滑動處理事件。這些事件是什麼?可以通知Controller去操作Model,更新Model數據,也可以直接更新Model數據,也可以是Controller更新View數據
舉例:用戶對界面進行操作,比如點擊,滑動界面(事先注冊的View),監聽的View被響應,告訴Controler進行處理響應事件,比如操作Model,訪問網絡數據,更新Model對象,然後更新界面View的數據,或控件的狀態變化
當將架構改為MVP以後,Presenter的出現,將Actvity視為View層,Presenter負責完成View層與Model層的交互。現在是這樣的:
View 對應於Activity,負責顯示數據,View的繪制以及與用戶交互Model 業務邏輯和實體模型Presenter 負責完成View於Model間的交互,處理著程序各種邏輯的分發,收到View層UI上的反饋命令、定時命令、系統命令等指令後分發處理邏輯交由Model層做具體的業務操作。如圖所示:

有圖觀察可知:MCV模式與MVP模式最明顯的區別就是,
MVC中是允許Model和View進行交互的,而MVP中很明顯,Model與View之間的交互由Presenter完成。還有一點就是Presenter與View之間的交互是通過接口的
1. 降低耦合度,實現了Model和View真正的完全分離,可以修改View而不影響Modle
2. 模塊職責劃分明顯,層次清晰
3. 隱藏數據
4. Presenter可以復用,一個Presenter可以用於多個View,而不需要更改Presenter的邏輯(當然是在View的改動不影響業務邏輯的前提下)
5. 利於測試驅動開發。
6. View可以進行組件化。在MVP當中,View不依賴Model。這樣就可以讓View從特定的業務場景中脫離出來,可以說View可以做到對業務完全無知。它只需要提供一系列接口提供給上層操作。這樣就可以做到高度可復用的View組件。
7. 代碼靈活性
1. Presenter中除了應用邏輯以外,還有大量的View->Model,Model->View的手動同步邏輯,造成Presenter比較笨重,維護起來會比較困難。
2. 由於對視圖的渲染放在了Presenter中,所以視圖和Presenter的交互會過於頻繁,view裡的行為太過復雜,應對復雜場景勢必造成代碼行為膨脹
3. 如果Presenter過多地渲染了視圖,往往會使得它與特定的視圖的聯系過於緊密。一旦視圖需要變更,那麼Presenter也需要變更了。
4. 額外的代碼復雜度及學習成本
例子:實現效果:簡單登陸界面功能,輸入姓名,密碼,然後點擊登陸按鍵,提示登陸結果,點擊清除按鍵,清除輸入內容
1)分析Model數據模型,實體類有什麼屬性和行為。
比如:這個例子中,登陸功能,需要一個用戶模型User
package com.example.juphome.mvpdemo.Login.bean;
/**
* Created by Juphome on 2017/1/15.
*/
public class User {
private String username ;
private String password ;
public String getUsername()
{
return username;
}
public void setUsername(String username)
{
this.username = username;
}
public String getPassword()
{
return password;
}
public void setPassword(String password)
{
this.password = password;
}
}
2)定義操作具體業務類的回調接口:OnLoginListener,用於回調監聽登陸結果狀態
package com.example.juphome.mvpdemo.Login.biz;
import com.example.juphome.mvpdemo.Login.bean.User;
/**
* Created by Juphome on 2017/1/15.
*/
public interface OnLoginListener {
void loginSuccess(User user);
void loginFailed();
}
定義操作業務類的抽象接口:IUserBiz
package com.example.juphome.mvpdemo.Login.biz;
import com.example.juphome.mvpdemo.Login.bean.User;
/**
* Created by Juphome on 2017/1/15.
*/
public interface OnLoginListener {
void loginSuccess(User user);
void loginFailed();
}
實現操作業務類的抽象接口:UserBiz
package com.example.juphome.mvpdemo.Login.biz;
import com.example.juphome.mvpdemo.Login.bean.User;
/**
* Created by Juphome on 2017/1/15.
*/
public class UserBiz implements IUserBiz{
@Override
public void login(final String username, final String password, final OnLoginListener loginListener) {
//模擬子線程耗時操作
new Thread()
{
@Override
public void run()
{
try
{
Thread.sleep(2000);
} catch (InterruptedException e)
{
e.printStackTrace();
}
//模擬登錄成功
if ("zhy".equals(username) && "123".equals(password))
{
User user = new User();
user.setUsername(username);
user.setPassword(password);
loginListener.loginSuccess(user);
} else
{
loginListener.loginFailed();
}
}
}.start();
}
}
定義契約類(接口)
使用契約類來統一管理view與presenter的所有的接口,這種方式使得view與presenter中有哪些功能,一目了然,維護起來也很方便。
Presenter是用作Model和View之間交互的橋梁,那麼應該有什麼方法呢?
其實也是主要看該功能有什麼操作,比如本例,兩個操作:login和clear。
package com.example.juphome.mvpdemo.Login.biz;
import com.example.juphome.mvpdemo.Login.bean.User;
/**
* Created by Juphome on 2017/1/15.
*/
public interface UserBizContract {
interface IUserLoginView {
String getUserName();
String getPassword();
void clearUserName();
void clearPassword();
void showLoading();
void hideLoading();
void toMainActivity(User user);
void showFailedError();
}
interface Presenter{
void login();
void clear();
}
}
package com.example.juphome.mvpdemo.Login.presenter;
import android.os.Handler;
import com.example.juphome.mvpdemo.Login.bean.User;
import com.example.juphome.mvpdemo.Login.biz.IUserBiz;
import com.example.juphome.mvpdemo.Login.biz.OnLoginListener;
import com.example.juphome.mvpdemo.Login.biz.UserBiz;
import com.example.juphome.mvpdemo.Login.biz.UserBizContract;
/**
* Created by Juphome on 2017/1/15.
*/
public class UserLoginPresenter implements UserBizContract.Presenter {
private IUserBiz userBiz;
private UserBizContract.IUserLoginView userLoginView;
private Handler mHandler = new Handler();
public UserLoginPresenter(UserBizContract.IUserLoginView userLoginView)
{
this.userLoginView = userLoginView;
this.userBiz = new UserBiz();
}
@Override
public void login() {
userLoginView.showLoading();
userBiz.login(userLoginView.getUserName(), userLoginView.getPassword(), new OnLoginListener()
{
@Override
public void loginSuccess(final User user)
{
//需要在UI線程執行
mHandler.post(new Runnable()
{
@Override
public void run()
{
userLoginView.toMainActivity(user);
userLoginView.hideLoading();
}
});
}
@Override
public void loginFailed()
{
//需要在UI線程執行
mHandler.post(new Runnable()
{
@Override
public void run()
{
userLoginView.showFailedError();
userLoginView.hideLoading();
}
});
}
});
}
@Override
public void clear() {
userLoginView.clearUserName();
userLoginView.clearPassword();
}
}
最後讓Model-View-Presenter動態聯系起來
讓Activity實現View的接口IUserLoginView,MVP中的View其實就是Activity,調用Presenter,處理業務操作,Presenter處理過程中,通知Activity界面友好提示,顯示緩沖數據圖標,Presenter處理業務操作完成後,回調通知Activity結果狀態,失敗或成功的數據
package com.example.juphome.mvpdemo.Login.view;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ProgressBar;
import android.widget.Toast;
import com.example.juphome.mvpdemo.Login.bean.User;
import com.example.juphome.mvpdemo.Login.biz.UserBizContract;
import com.example.juphome.mvpdemo.Login.presenter.UserLoginPresenter;
import com.example.juphome.mvpdemo.R;
/**
* Created by Juphome on 2017/1/15.
*/
public class UserLoginActivity extends Activity implements UserBizContract.IUserLoginView {
private EditText mEtUsername, mEtPassword;
private Button mBtnLogin, mBtnClear;
private ProgressBar mPbLoading;
private UserLoginPresenter mUserLoginPresenter = new UserLoginPresenter(this);
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_user_login);
initViews();
}
private void initViews()
{
mEtUsername = (EditText) findViewById(R.id.id_et_username);
mEtPassword = (EditText) findViewById(R.id.id_et_password);
mBtnClear = (Button) findViewById(R.id.id_btn_clear);
mBtnLogin = (Button) findViewById(R.id.id_btn_login);
mPbLoading = (ProgressBar) findViewById(R.id.id_pb_loading);
mBtnLogin.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v)
{
mUserLoginPresenter.login();
}
});
mBtnClear.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v)
{
mUserLoginPresenter.clear();
}
});
}
@Override
public String getUserName()
{
return mEtUsername.getText().toString();
}
@Override
public String getPassword()
{
return mEtPassword.getText().toString();
}
@Override
public void clearUserName()
{
mEtUsername.setText("");
}
@Override
public void clearPassword()
{
mEtPassword.setText("");
}
@Override
public void showLoading()
{
mPbLoading.setVisibility(View.VISIBLE);
}
@Override
public void hideLoading()
{
mPbLoading.setVisibility(View.GONE);
}
@Override
public void toMainActivity(User user)
{
Toast.makeText(this, user.getUsername() +
" login success , to MainActivity", Toast.LENGTH_SHORT).show();
}
@Override
public void showFailedError()
{
Toast.makeText(this,
"login failed", Toast.LENGTH_SHORT).show();
}
}
使用MVP模式的步驟:
定義mode層的實體類,操作業務類的接口操作業務類完成的結果狀態監聽接口定義view的接口。定義Presenter接口實現定義好的View接口和Presenter接口讓MVP動起來讓Acivity實現view接口,在Activity中創建Presenter引用對象,用Presenter對象,操作Model的業務邏輯處理,Model層處理完成後,通過業務監聽回調接口,告訴Presenter處理業務的結果如何,最後Persenter通過VIew接口,讓Activity進行頁面數據更新

[android]ShareSDK——內容分享和短信驗證
前言新版本ShareSDK的分享和短信驗證,按官網的文檔,都需要添加一個標簽,而分享和短息驗證的這個標簽內容都一樣。會沖突。解決辦法:分享用舊版本,短信驗證用新版本。後面
Android實現自定義的彈幕效果
一、效果圖先來看看效果圖吧~~二、實現原理方案1、自定義ViewGroup-XCDanmuView,繼承RelativeLayout來實現,當然也可以繼承其他三大布局類哈
RxAndroid之app的生命周期管理RxLifecycle
管理Activity(Fragment、dialogFragment)的生命周期需要在build.gradle中加入compile 'com.trello:rxl
Android中handler運行原理
在android中提供了一種異步回調機制Handler,使用它,我們可以在完成一個很長時間的任務後做出相應的通知 handler基本使用: 在主線