MVP Architecture on Android

Android面试必问!啃完999页Android面试高频宝典,完整PDF 前言 首先介绍一下自己,计算机水本,考研与我无缘。之前在帝都某公司算法部实习,公司算大公司吧,然而个人爱好偏开发,大二的时候写个一个app,主要是用各种框架。 1. Android架构设计模式 MVC架构设计模式:MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写。 MVP架构设计模式:MVC全名是Model View Persenter,MVP由MVC演变而来,是现在主流的开发模式。 MVVM架构设计模式:MVVM全名是M 阅读详情

原文:http://blog.youkuaiyun.com/lmj623565791/article/details/46596109

一、概述

对于MVP(Model View Presenter),大多数人都能说出一二:“MVC的演化版本”,“让Model和View完全解耦”等等。本篇博文仅是为了做下记录,提出一些自己的看法,和帮助大家如何针对一个Activity页面去编写针对MVP风格的代码。

对于MVP,我的内心有一个问题:

为何这个模式出来后,就能被广大的Android的程序员接受呢?

问了些程序员,他们对于MVP的普遍的认识是:“代码很清晰,不过增加了很多类”。我在第一次看到MVP的时候,看了一个demo,看完以后觉得非常nice(但是回过头来,自己想个例子写,就头疼写不出来,当然这在后文会说)。nice的原因还是因为,这个模式的确让代码的清晰度有了很大的提升。

那么,提升一般都是对比出来的,回顾下,没有应用MVP的代码结构。很多人说明显是MVC么:

  • View:对应于布局文件
  • Model:业务逻辑和实体模型
  • Controllor:对应于Activity

看起来的确像那么回事,但是细细的想想这个View对应于布局文件,其实能做的事情特别少,实际上关于该布局文件中的数据绑定的操作,事件处理的代码都在Activity中,造成了Activity既像View又像Controller(当然了Data-Binder的出现,可能会让View更像View吧)。这可能也就是为何,在https://github.com/konmik/konmik.github.io/wiki/Introduction-to-Model-View-Presenter-on-Android中有一句这样的话:

Most of the modern Android applications just use View-Model architecture,everything is connected with Activity.

而当将架构改为MVP以后,Presenter的出现,将Actvity视为View层,Presenter负责完成View层与Model层的交互。现在是这样的:

  • View 对应于Activity,负责View的绘制以及与用户交互
  • Model 依然是业务逻辑和实体模型
  • Presenter 负责完成View于Model间的交互

ok,先简单了解下,文中会有例子到时候可以直观的感受下。

小总结下,也就是说,之所以让人觉得耳目一新,是因为这次的跳跃是从并不标准的MVC到MVP的一个转变,减少了Activity的职责,简化了Activity中的代码,将复杂的逻辑代码提取到了Presenter中进行处理。与之对应的好处就是,耦合度更低,更方便的进行测试。借用两张图(出自:https://github.com/konmik/konmik.github.io/wiki/Introduction-to-Model-View-Presenter-on-Android),代表上述的转变:


转变为:


二、MVP 与 MVC 区别

ok,上面说了一堆理论,下面我们还是需要看一看MVC与MVP的一个区别,请看下图(来自:本文):


其实最明显的区别就是,MVC中是允许Model和View进行交互的,而MVP中很明显,Model与View之间的交互由Presenter完成。还有一点就是Presenter与View之间的交互是通过接口的(代码中会体现)。

还有一堆概念性的东西,以及优点就略了,有兴趣自行百度。下面还是通过一些简单的需求来展示如何编写MVP的demo。

三、Simple Login Demo

效果图:


看到这样的效果,先看下完工后的项目结构:


ok,接下来开始一步一步的编写思路。

(一)Model

首先实体类User不用考虑这个肯定有,其次从效果图可以看到至少有一个业务方法login(),这两点没什么难度,我们首先完成:

package com.zhy.blogcodes.mvp.bean;

/**
 * Created by zhy on 15/6/18.
 */
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;
    }
}
package com.zhy.blogcodes.mvp.biz;

/**
 * Created by zhy on 15/6/19.
 */
public interface IUserBiz
{
    public void login(String username, String password, OnLoginListener loginListener);
}
import com.zhy.blogcodes.mvp.bean.User;

/**
 * Created by zhy on 15/6/19.
 */
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();
    }
}
package com.zhy.blogcodes.mvp.biz;

import com.zhy.blogcodes.mvp.bean.User;

/**
 * Created by zhy on 15/6/19.
 */
public interface OnLoginListener
{
    void loginSuccess(User user);

    void loginFailed();
}

实体类不用说,至于业务类,我们抽取了一个接口,一个实现类这也很常见~~login方法,一般肯定是连接服务器的,是个耗时操作,所以我们开辟了子线程,Thread.sleep(2000)模拟了耗时,由于是耗时操作,所以我们通过一个回调接口来通知登录的状态。

其实这里还是比较好写的,因为和传统写法没区别。

(二) View

上面我们说过,Presenter与View交互是通过接口。所以我们这里需要定义一个ILoginView,难点就在于应该有哪些方法,我们看一眼效果图:

可以看到我们有两个按钮,一个是login,一个是clear;

login说明了要有用户名、密码,那么对应两个方法:

    String getUserName();

    String getPassword();
再者login是个耗时操作,我们需要给用户一个友好的提示,一般就是操作ProgressBar,所以再两个:
    void showLoading();

    void hideLoading();
login当然存在登录成功与失败的处理,我们主要看成功我们是跳转Activity,而失败可能是去给个提醒:
    void toMainActivity(User user);

    void showFailedError();
ok,login这个方法我们分析完了~~还剩个clear那就简单了:
    void clearUserName();

    void clearPassword();
综上,接口完整为:
package com.zhy.blogcodes.mvp.view;

import com.zhy.blogcodes.mvp.bean.User;

/**
 * Created by zhy on 15/6/19.
 */
public interface IUserLoginView
{
    String getUserName();

    String getPassword();

    void clearUserName();

    void clearPassword();

    void showLoading();

    void hideLoading();

    void toMainActivity(User user);

    void showFailedError();

}

有了接口,实现就太好写了~~~

总结下,对于View的接口,去观察功能上的操作,然后考虑:

  • 该操作需要什么?(getUserName, getPassword)
  • 该操作的结果,对应的反馈?(toMainActivity, showFailedError)
  • 该操作过程中对应的友好的交互?(showLoading, hideLoading)

下面贴一下我们的View的实现类,哈,其实就是Activity,文章开始就说过,MVP中的View其实就是Activity。

package com.zhy.blogcodes.mvp;

import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ProgressBar;
import android.widget.Toast;

import com.zhy.blogcodes.R;
import com.zhy.blogcodes.mvp.bean.User;
import com.zhy.blogcodes.mvp.presenter.UserLoginPresenter;
import com.zhy.blogcodes.mvp.view.IUserLoginView;

public class UserLoginActivity extends ActionBarActivity implements 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();
    }
}

对于在Activity中实现我们上述定义的接口,是一件很容易的事,毕竟接口引导我们去完成。

最后看我们的Presenter。

(三)Presenter

Presenter是用作Model和View之间交互的桥梁,那么应该有什么方法呢?

其实也是主要看该功能有什么操作,比如本例,两个操作:login和clear。

package com.zhy.blogcodes.mvp.presenter;

import android.os.Handler;

import com.zhy.blogcodes.mvp.bean.User;
import com.zhy.blogcodes.mvp.biz.IUserBiz;
import com.zhy.blogcodes.mvp.biz.OnLoginListener;
import com.zhy.blogcodes.mvp.biz.UserBiz;
import com.zhy.blogcodes.mvp.view.IUserLoginView;


/**
 * Created by zhy on 15/6/19.
 */
public class UserLoginPresenter
{
    private IUserBiz userBiz;
    private IUserLoginView userLoginView;
    private Handler mHandler = new Handler();

    public UserLoginPresenter(IUserLoginView userLoginView)
    {
        this.userLoginView = userLoginView;
        this.userBiz = new UserBiz();
    }

    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();
                    }
                });

            }
        });
    }

    public void clear()
    {
        userLoginView.clearUserName();
        userLoginView.clearPassword();
    }


}

注意上述代码,我们的presenter完成二者的交互,那么肯定需要二者的实现类。大致就是从View中获取需要的参数,交给Model去执行业务方法,执行的过程中需要的反馈,以及结果,再让View进行做对应的显示。


参考链接:

Android 架构MVC MVP MVVM+实例 工作原理1.View接受用户的交互请求。2.View将请求转交给Controller。3.Controller操作Model进行数据更新。4.数据更新之后,Model通知View数据变化。5.View显示更新之后的数据。MVC的缺点随着界面及其逻辑的复杂度不断提升,Activity类的职责不断增加,以致变得庞大臃肿。MVP是什么======MVP是MVC架构的一个演化版,全称是Model-View-Presenter。将MVC中的V和C结合生成MVP中的V,引入新的伙伴Presenter。 阅读详情

相关推荐

Android中对MVC,MVP,MVVM架构的理解

但是随着软件越来越来复杂,会发现这样的写法不是太好,有些缺陷,Controller和View越来越耦合了,Controller指挥View去显示,具体怎么显示Controller是不关注的,比如setContentView(R.layout.activity_m_v_c),和具体的摆放逻辑全部是在xml中进行摆放布局的,但是Controller层要操控具体的数据应该放在哪个控件上,随着软件越来越大,Controller和View层的关系越来越紧密,所以引入了MVP架构。1、Model层对应的代码。

路宇的博客 2453

Android技术框架篇(二):MVP框架

mvp架构的介绍

看,好自为之的博客!!! 6634

SAP PPDS启发式排产实战:从零配置到自定义规则开发(附ABAP代码示例)

本文详细介绍了SAP PPDS启发式排产的实战应用,从基础配置到自定义规则开发的全流程。通过ABAP代码示例,展示了如何实现多目标优化、实时响应和约束可视化,帮助企业提升订单交付率、减少设备闲置时间。文章还包含开发环境准备、标准模板解析、自定义开发步骤及性能优化技巧,适合制造业数字化转型的实践参考。

seed的博客 183

Android MVP架构模式

详解Android如何实现MVP架构

保温杯拖把风扇的博客 5129

GD32F303定时器配置:实现两路互补PWM输出与相位控制

本文详细解析了基于GD32F303定时器实现两路互补PWM输出与精确相位控制的方法。通过配置TIMER2的中间对齐模式,结合REMAP功能解决引脚复用问题,从硬件层面稳定生成相位差180度的互补PWM信号,适用于电机驱动、开关电源等对时序要求苛刻的应用场景。

weixin_29182481的博客 304

第1关:STL模板之queue实例一:最少个数

头歌自创答案

xiyunSacire的博客 818

从0到1开发MVP应用:基于android-kotlin-mvp-architecture的实战案例

android-kotlin-mvp-architecture是一个基于Kotlin语言实现MVP架构的示例应用,集成了Dagger2、Room、RxJava等主流开发框架,为Android开发者提供了完整的MVP架构参考。本文将带你快速掌握MVP架构的核心概念和实战技巧,从零开始构建一个结构清晰、易于维护的Android应用。 ## 📌 为什么选择MVP架构? MVP(Model-View

gitblog_00115的博客 1134

解决PADs VX2.7安装中的License失效与软件卡死问题

本文详细解析了PADs VX2.7安装过程中常见的License失效与软件卡死问题,提供了从破解工具选择、环境变量设置到输入法兼容性调整等实用解决方案。特别推荐使用Siemens EDA系列新版破解工具,并分享性能调优与定期维护技巧,帮助工程师高效解决安装难题。

weixin_29234239的博客 813

Android应用架构演进之路:从MVC、MVP到MVVM与Clean Architecture

架构设计没有绝对的银弹,只有最适合当前业务场景的选择。对于绝大多数项目:从的模式开始,这是目前投入产出比最高的架构。对于大型复杂项目:在MVVM的基础上引入的分层思想,能让你的应用在未来的迭代中保持清晰和健壮。

m0_65382359的博客 1360

华为OD机试真题 新系统 9月16号 【统计特殊数字】

华为OD新系统机试真题【统计特殊数字】,提供C语言、Java、C++、Python、Go、JavaScript源码实现,并提供完整思路讲解,以及在线OJ模拟做题。华为OD机试真题【统计特殊数字】。

qq_45776114的博客 766

EtherCAT总线运动控制学习笔记(RXXW_Dor)

说到总线控制,就要说到报文、对象字典、PN通信我们大部分会说报文,EtherCAT通信我们常说对象字典,叫法不一样,但是原理基本一致,下面我们简单认识下上面是对象字典。

RXXW_Dor的博客 5428

Android Kotlin MVP Clean Architecture 项目指南

Android Kotlin MVP Clean Architecture 项目指南 欢迎来到 android-kotlin-mvp-clean-architecture 开源项目的学习之旅。此项目以Kotlin为核心,采用Model-View-Presenter(MVP)设计模式,并遵循Clean Architecture原则,旨在提供一种结构清晰、易于测试和维护的Android应用程序开发框架...

gitblog_00228的博客 1042

【深度学习新浪潮】Qwen3.5-397B-A17B 深度解析与工程部署实战:超大MoE模型的推理加速与落地

Qwen3.5-397B-A17B是当前开源社区综合能力最强、部署效率最高的超大模型,其MoE架构彻底解决了“大模型难部署、慢、贵”的痛点。

专注:太空算力、AI infra、异构调度、大模型成本工程 1708

学习Android Architecture Blueprints(一)-mvp分支

1. 前言在几个月前,google sample组织下,创建了一个叫做android-architecture的仓库,第一时间引爆了Android圈,这个项目在于指导使用不同的架构指导我们如何解决测试、维护以及扩展的难题,让我们一一学习下。项目地址2. todo-mvp分支在去年的时候,mvp火了起来,然而,在国内的文章当中,大多是的试讲m-v-p分开来写,我今年毕设使用这种模式,发现一个很严重的问

_StriveG的专栏 2191

【项目实战】TARA威胁分析和风险评估

TARA是信息安全领域中的一种风险评估方法,在汽车信息安全的上下文中,TARA分析特别重要,因为它可以帮助识别和管理与智能网联车辆相关的各种威胁,包括数据泄露、未经授权的访问、远程操控等。通过TARA分析,企业可以制定出针对性的安全目标、产品要求和产品安全声明,以确保汽车及其零部件符合相关的信息安全标准和法规。此外,TARA分析还可以与数字化建模系统结合,以更系统化和高效的方式进行风险评估和管理。

奶爸的编程之路,也就一周冷个三天 2709

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

如何用Kotlin构建MVP应用?android-kotlin-mvp-architecture完整入门教程

android-kotlin-mvp-architecture是一个基于Kotlin语言实现MVP架构的示例应用,它整合了Dagger2、Room、RxJava、FastAndroidNetworking和PlaceholderView等主流Android开发库,为开发者提供了清晰的架构设计参考。本文将带你从零开始了解如何使用这个项目快速构建MVP模式的Android应用。 ## 📌 什么是M

gitblog_00615的博客 1075

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

Android-MVP-Architecture:快速搭建高效Android应用的利器

Android-MVP-Architecture:快速搭建高效Android应用的利器 项目介绍 Android-MVP-Architecture 是一个开源的Android项目模板,旨在帮助开发者快速搭建基于MVP(Model-View-Presenter)架构的应用程序。该项目集成了RxJava2和Retrofit,使得开发者能够轻松实现数据处理和网络请求,从而专注于业务逻辑的开发。通过简单的...

gitblog_00938的博客 566

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

iOS-MVP-Clean-Architecture代码组织:Screaming Architecture在iOS项目中的应用

iOS-MVP-Clean-Architecture是一个专为演示MVP(Model View Presenter)和Clean Architecture概念而构建的iOS应用项目。本文将深入探讨该项目如何运用Screaming Architecture理念进行代码组织,帮助开发者打造结构清晰、易于维护的iOS应用架构。 ## 什么是Screaming Architecture? Scream

gitblog_00737的博客 716

终极Android架构指南:深入理解android-kotlin-mvp-architecture的MVP实现

android-kotlin-mvp-architecture是一个功能完整的Android应用架构示例项目,它巧妙结合了MVP(Model-View-Presenter)设计模式与Kotlin语言特性,并集成了Dagger2、Room、RxJava2和FastAndroidNetworking等主流开发库,为Android开发者提供了一套清晰、可维护的架构解决方案。 ## MVP架构核心组件解

gitblog_01200的博客 485

基于Android Architecture Blueprints的MVP案例分析与实现

基于Android Architecture Blueprints的MVP案例分析与实现 株洲新程IT教育 李赞红 1 概述          Android Architecture Blueprints是Google官方版本的MVP实现,我们通过https://github.com/googlesamples/android-architecture/tree/todo-mvp可以阅读具

Android学习博客 2156

Awesome Android Architecture 教程

Awesome Android Architecture 教程 项目介绍 Awesome Android Architecture 是一个集合了多种 Android 架构模式的开源项目,旨在帮助开发者理解和应用不同的架构模式,以构建更健壮、可维护的 Android 应用。该项目包含了 MVP、MVC、MVVM、Clean Architecture 等多种架构模式的示例和最佳实践。 项目快速启动 克...

gitblog_00454的博客 577

Buffer Android架构深度解析:Clean Architecture与MVP/MVVM变体实现

Buffer Android应用采用Clean Architecture架构模式,并结合MVP和MVVM两种变体实现,为开发者提供了清晰的代码组织方式和灵活的功能扩展能力。本文将深入剖析这一架构设计,帮助新手开发者理解如何构建可维护、可测试的Android应用。 [![Buffer Android应用界面展示](https://raw.gitcode.com/gh_mirrors/and/and

gitblog_00694的博客 320

PlaceholderView列表渲染技巧:android-kotlin-mvp-architecture UI实现

android-kotlin-mvp-architecture是一个基于Kotlin语言实现MVP架构的Android示例项目,集成了Dagger2、Room、RxJava2等主流框架,同时采用PlaceholderView实现高效的列表渲染功能。本文将分享该项目中PlaceholderView的核心使用技巧,帮助开发者快速掌握UI实现的最佳实践。 ## 📌 什么是PlaceholderVie

gitblog_00170的博客 938

Android-Architecture:基于MVP与Clean架构的Android项目实践

Android-Architecture:基于MVP与Clean架构的Android项目实践 本文将为您介绍一个开源项目:Android-Architecture。该项目是一个基于MVP(Model-View-Presenter)与Clean架构的Android实践项目,主要使用Java编程语言开发。 项目基础介绍 Android-Architecture项目是一个旨在探索在Android开发中应...

gitblog_00669的博客 519

Android Architecture Samples架构比较:MVC、MVP、MVVM、MVI架构对比

在Android开发中,选择合适的架构模式直接影响应用的可维护性、测试难度和团队协作效率。你是否曾面临代码混乱、Bug频发、迭代困难的问题?本文将通过Google官方Android Architecture Samples项目,解析MVC、MVP、MVVM和MVI四种主流架构的优缺点,帮助你为下一个项目做出明智决策。 读完本文你将了解: - 四种架构的核心设计思想与组件关系 - 各架构在实际开发...

gitblog_00183的博客 387

5分钟上手android-kotlin-mvp-architecture:环境搭建与项目运行

android-kotlin-mvp-architecture是一个基于Kotlin语言实现MVP架构的Android示例项目,集成了Dagger2、Room、RxJava等主流开发框架,为开发者提供了清晰的架构设计和最佳实践参考。通过本指南,你将快速完成环境搭建并运行项目,体验专业级Android应用开发流程。 ## 📋 准备工作:开发环境要求 在开始前,请确保你的开发环境满足以下条件:

gitblog_00131的博客 947
上一篇: Android小知识
下一篇: Flux Architecture on Android
Inconsolabl
博客等级 码龄15年 5粉丝 20原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值