android MVP 实现查询手机号归属地

传统的MVC 在Android 实现

  1. Model  实体模型 和业务逻辑
  2. View 这里对应布局文件
  3. Controller 这里对应的是Activity 

MVC  在Android 上的实现,会让Activity 又像View 又像Controller ,代码变得越来越臃肿,越来越不可控。MVP 的出现解决了这个问题。

MVP 

  1. Model 依然是实体模型和业务逻辑
  2. View 这里对应 Activity  和布局文件
  3. Presenter 负责Model 和View 的交互

MVP 与MVC 的区别:

 

 

 

 

 

 

 

 

 

从图中可以看出 MVC 中Model 可以和View 交互的,而MVP中 Model 和View 不能交互,他们是通过Presenter 交互的。

 

查询手机是归属地 demo 实现:

 

引用两个库:

    implementation 'com.squareup.okhttp3:okhttp:3.11.0'
    implementation 'com.google.code.gson:gson:2.8.5'

权限,基本的网络请求需要网络权限:

  <uses-permission android:name="android.permission.INTERNET"/>

先贴上封装的HttpUtils:

public class HttpUtils {

    String mUrl ;
    Map<String ,String> mParam;

    HttpResponse mHttpResponse;

    Handler UIHandler = null;
    OkHttpClient okHttpClient = null;

    Gson gson = null;
    private static HttpUtils mInstance ;

    /**
     * 初始化一些基本数据
     */
    private HttpUtils()
    {
        okHttpClient = new OkHttpClient();
        gson = new Gson();
        UIHandler = new Handler(Looper.getMainLooper());

    }

    public  static HttpUtils getInstance()
    {
        if(mInstance == null)
        {
            synchronized(HttpUtils.class)
            {
                if(mInstance == null)
                {
                    mInstance = new HttpUtils();
                }
            }
        }
        return mInstance ;

    }

    /**
     * 回调接口
     */
    public interface HttpResponse
    {
        void onSuccess(Object object);
        void onFail(String object);
    }
    public void sendPostHttp(String url ,Map<String,String> param)
    {
          sendHttp(url,param,true);
    }

    public void sendGetHttp(String url ,Map<String,String> param,HttpResponse httpResponse)
    {
         mHttpResponse = httpResponse ;
         sendHttp(url,param,false);
    }

    public void sendHttp(String url,Map<String,String> param,boolean isPost)
    {
        mUrl = url ;
        mParam = param;
        //请求逻辑
       run(isPost);
    }

    private void run(boolean isPost)
    {

        Request request = createRequest(isPost);
        okHttpClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                if(mHttpResponse != null)
                {
                    UIHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            mHttpResponse.onFail("请求错误");
                        }
                    });
                }
            }

            @Override
            public void onResponse(Call call, final Response response) throws IOException {
                if(mHttpResponse == null)
                    return ;
                UIHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            String json = response.body().string();
                            int index = json.indexOf("{");
                            json = json.substring(index);
                            Phone phone = gson.fromJson(json,Phone.class);
                            mHttpResponse.onSuccess(phone);
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                });
            }
        });
    }

    private Request createRequest(boolean isPost)
    {
        Request request = null;
        if(isPost)
        {
            MultipartBody.Builder builder = new MultipartBody.Builder();
            builder.setType(MultipartBody.FORM);
            //遍历Map
            Iterator<Map.Entry<String,String>> iterator = mParam.entrySet().iterator();
            while(iterator.hasNext())
            {
                Map.Entry<String,String> entry = iterator.next();
                builder.addFormDataPart(entry.getKey(),entry.getValue());
                request = new Request.Builder().url(mUrl).post(builder.build()).build();
            }
        }else
        {
          String urlStr = mUrl +"?"+MapParamToString(mParam);
          request = new Request.Builder().url(urlStr).build();
        }

        return  request ;
    }

    private  String MapParamToString(Map<String,String> mParam)
    {
        StringBuilder stringBuilder = new StringBuilder();
        Iterator<Map.Entry<String,String>> iterator = mParam.entrySet().iterator();
        while(iterator.hasNext())
        {
            Map.Entry<String,String> entry = iterator.next();
            stringBuilder.append(entry.getKey()+"="+entry.getValue()+"&");

        }
        String str = stringBuilder.toString().substring(0,stringBuilder.length());
        return str ;
    }
}

Model 编写:这里的model 就是查询手机归属的Phone 类:

public class Phone {

    String  telString;
    String province;
    String carrier;
    String catName;

    public String getTelString() {
        return telString;
    }

    public void setTelString(String telString) {
        this.telString = telString;
    }

    public String getProvince() {
        return province;
    }

    public void setProvince(String province) {
        this.province = province;
    }

    public String getCarrier() {
        return carrier;
    }

    public void setCarrier(String carrier) {
        this.carrier = carrier;
    }

    public String getCatName() {
        return catName;
    }

    public void setCatName(String catName) {
        this.catName = catName;
    }
}

 View  这里写贴上布局文件:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    android:orientation="vertical"
    >


    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="手机号查询"
        android:layout_gravity="center"
        android:layout_marginTop="20dp"
        />
    <EditText
        android:id="@+id/edit_query"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:layout_margin="20dp"
        android:hint="请输入手机号码"
        />

    <Button
        android:id="@+id/button_query"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="查询"
        android:layout_gravity="center"
        android:layout_margin="20dp"
        />

    <TextView
        android:id="@+id/result"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="查询结果"
        android:layout_gravity="center"
        android:layout_margin="20dp"
        />

</LinearLayout>

Presenter 是通过接口与View 交互的,这里要实现两个接口:

/**
 *  基本Loading 接口
 */
public interface MvpLoadingView {
    void showLoading();
    void hidenLoading();
}
/**
 * 更新UI接口
 */
public interface MvpMainView extends MvpLoadingView{

   void showToast(String msg);
   void updateView(Object object);

}

View 最后实现的部分 ,就是Activity 了:

public class MainActivity extends AppCompatActivity implements MvpMainView {

    EditText edit_query ;
    TextView button_query,result ;

    MainPresenter mainPresenter ;

    private ProgressDialog progressDialog;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initId();
        initEvent();
        mainPresenter = new MainPresenter(this);
        mainPresenter.attach(this);
    }

    private void initId()
    {
        edit_query = findViewById(R.id.edit_query);
        button_query = findViewById(R.id.button_query);
        result = findViewById(R.id.result);
    }
    private void initEvent()
    {
        button_query.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
             String phone = edit_query.getText().toString();
                mainPresenter.searchPhoneInfo(phone);
            }
        });

        edit_query.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {

            }

            @Override
            public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {

            }

            @Override
            public void afterTextChanged(Editable editable) {
             if(editable.toString().length()>=11)
             {
                 String phone = edit_query.getText().toString();
                 mainPresenter.searchPhoneInfo(phone);
             }
            }
        });
    }

    @Override
    public void showToast(String msg) {

    }

    @Override
    public void updateView(Object object) {

        Phone phone = (Phone)object;
        result.setText("手机号码:"+phone.getTelString()+"\n"+"省份:"+phone.getProvince());
    }

    @Override
    public void showLoading() {
        progressDialog = new ProgressDialog(this);;
        progressDialog.setMessage("loading");
        progressDialog.show();
    }

    @Override
    public void hidenLoading() {
        progressDialog.dismiss();
    }
}

剩下来就是Presenter 的编写了:

/**
 * 基本 Presenter
 */
public class BasePresenter {


    Context mContext ;
    public void attach(Context context)
    {
        mContext = context;
    }
    public void onPause(){}
    public void onResume(){}
    public void onDestroy(){}
}
/**
 * 查询手机归属 presenter
 */
public class MainPresenter extends BasePresenter{

    public static final String url = "https://tcc.taobao.com//cc/json/mobile_tel_segment.htm";
    MvpMainView mvpMainView ;

    public Phone getmPhone() {
        return mPhone;
    }

    Phone mPhone ;
  public MainPresenter(MvpMainView mainView)
  {
      mvpMainView = mainView ;
  }
  public void searchPhoneInfo(String phone)
  {
      if(phone.length() !=11)
      {
          mvpMainView.showToast("请输入正确的手机号码");
          return ;
      }
      mvpMainView.showLoading();
      sendHttp(phone);
  }

  private void sendHttp(String phone)
  {
      Map<String,String > map = new HashMap<>();
      map.put("tel",phone);

      HttpUtils.getInstance().sendGetHttp(url, map, new HttpUtils.HttpResponse() {
          @Override
          public void onSuccess(Object object) {
              mvpMainView.hidenLoading();
              mvpMainView.updateView(object);
          }

          @Override
          public void onFail(String object) {
              mvpMainView.showToast(object);
              mvpMainView.hidenLoading();
          }
      });
      //httpUtils.sendGetHttp(url,map);

  }

  private Phone parsePhone(String json)
  {
      Phone phone = new Phone();

      try {
          JSONObject jsonObject = new JSONObject(json);
          String value = jsonObject.getString("telString");
          phone.setTelString(value);
          value = jsonObject.getString("province");
          phone.setProvince(value);
          value = jsonObject.getString("catName");
          phone.setCatName(value);
          value = jsonObject.getString("carrier");
          phone.setCarrier(value);
      } catch (JSONException e) {
          e.printStackTrace();
      }
   return phone;

  }

  private Phone parseWithGson(String json)
  {
      Gson gson = new Gson();
      Phone phone = gson.fromJson(json,Phone.class);
      return phone;
  }



}

最终实现效果:

 

参考:

浅谈 MVP in Android

号码归属地查询实用工具

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MVP(Model-View-Presenter)是一种软件架构模式,它将软件应用程序分为三个基本部分:模型(Model)、视图(View)和表示器(Presenter)。MVP模式的主要目的是实现UI和业务逻辑之间的分离,使得代码更加可维护和可扩展。 下面是一个简单的MVP模式实现Android登录功能: 1. 创建一个LoginActivity类作为View层,它将负责展示登录页面,处理用户的输入和显示登录结果。 ``` public class LoginActivity extends AppCompatActivity implements LoginContract.View { private EditText mUserNameEditText; private EditText mPasswordEditText; private Button mLoginButton; private TextView mResultTextView; private LoginContract.Presenter mPresenter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_login); mUserNameEditText = findViewById(R.id.user_name_edit_text); mPasswordEditText = findViewById(R.id.password_edit_text); mLoginButton = findViewById(R.id.login_button); mResultTextView = findViewById(R.id.result_text_view); mPresenter = new LoginPresenter(this); mLoginButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { String userName = mUserNameEditText.getText().toString(); String password = mPasswordEditText.getText().toString(); mPresenter.login(userName, password); } }); } @Override public void showResult(String result) { mResultTextView.setText(result); } } ``` 2. 创建一个LoginPresenter类作为Presenter层,它将负责处理业务逻辑,调用Model层进行数据处理,并将结果返回给View层。 ``` public class LoginPresenter implements LoginContract.Presenter { private LoginContract.View mView; private LoginModel mModel; public LoginPresenter(LoginContract.View view) { mView = view; mModel = new LoginModel(); } @Override public void login(String userName, String password) { boolean result = mModel.checkUser(userName, password); if (result) { mView.showResult("登录成功"); } else { mView.showResult("登录失败"); } } } ``` 3. 创建一个LoginModel类作为Model层,它将负责进行数据处理,例如检查用户名和密码是否匹配。 ``` public class LoginModel { public boolean checkUser(String userName, String password) { // 进行用户名和密码的匹配,这里假设用户名为admin,密码为123456 return userName.equals("admin") && password.equals("123456"); } } ``` 4. 创建一个LoginContract接口,它定义了View层和Presenter层的接口方法。 ``` public interface LoginContract { interface View { void showResult(String result); } interface Presenter { void login(String userName, String password); } } ``` 通过以上步骤,我们就完成了一个简单的MVP模式实现Android登录功能。在这个例子中,View层处理UI展示和用户输入,Presenter层处理业务逻辑,并调用Model层进行数据处理和返回结果,Model层仅处理数据。这种分层架构可以使代码更加清晰、易于维护和扩展。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值