Android高级开发之【OkHttp】详解(附项目源码)

简介: 文章大纲 一、OkHttp简介 二、OkHttp简单使用 三、OkHttp封装 四、项目源码下载 一、OkHttp简介 1. 什么是OkHttp 一般在Java平台上,我们会使用Apache HttpClient作为Http客户端,用于发送 HTTP 请求,并对响应进行处理。

文章大纲

一、OkHttp简介
二、OkHttp简单使用
三、OkHttp封装
四、项目源码下载

一、OkHttp简介

1. 什么是OkHttp

一般在Java平台上,我们会使用Apache HttpClient作为Http客户端,用于发送 HTTP 请求,并对响应进行处理。比如可以使用http客户端与第三方服务(如SSO服务)进行集成,当然还可以爬取网上的数据等。OKHttp与HttpClient类似,也是一个Http客户端,提供了对 HTTP/2 和 SPDY 的支持,并提供了连接池,GZIP 压缩和 HTTP 响应缓存功能。

2. OkHttp优点

(1)支持HTTP2/SPDY(SPDY是Google开发的基于TCP的传输层协议,用以最小化网络延迟,提升网络速度,优化用户的网络使用体验)
(2)socket自动选择最好路线,并支持自动重连,拥有自动维护的socket连接池,减少握手次数,减少了请求延迟,共享Socket,减少对服务器的请求次数
(3)基于Headers的缓存策略减少重复的网络请求
(4)拥有Interceptors轻松处理请求与响应(自动处理GZip压缩)

3. OkHttp功能

(1)一般的get请求
(2)一般的post请求
(3)基于Http的文件上传
(4)文件下载
(5)上传下载的进度回调
(6)加载图片
(7)支持请求回调,直接返回对象、对象集合
(8)支持session的保持
(9)支持自签名网站https的访问,提供方法设置下证书就行
(10)支持取消某个请求

3. OkHttp使用步骤

(1)get请求的步骤,首先构造一个Request对象,参数最起码有个url,当然你可以通过Request.Builder设置更多的参数比如:header、method等。
(2)然后通过request的对象去构造得到一个Call对象,类似于将你的请求封装成了任务,既然是任务,就会有execute()和cancel()等方法。
(3)最后,我们希望以异步的方式去执行请求,所以我们调用的是call.enqueue,将call加入调度队列,然后等待任务执行完成,我们在Callback中即可得到结果。
(4)onResponse回调的参数是response,一般情况下,比如我们希望获得返回的字符串,
可以通过response.body().string()获取;如果希望获得返回的二进制字节数组,则调用response.body().bytes();如果你想拿到返回的inputStream,则调用response.body().byteStream()
(5)看到这,你可能会奇怪,竟然还能拿到返回的inputStream,看到这个最起码能意识到一点,这里支持大文件下载,有inputStream我们就可以通过IO的方式写文件。不过也说明一个问题,这个onResponse执行的线程并不是UI线程。的确是的,如果你希望操作控件,还是需要使用handler等
(6)okHttp还支持GJson的处理方式
(7)okhttp支持同步请求和异步请求,Call call = client.newCall(request);为同步请求,发送请求后,就会进入阻塞状态,知道收到响应call.enqueue(new Callback()为异步请求
(8)在okhttp3.Callback的回调方法里面有个参数是Call 这个call可以单独取消相应的请求,随便在onFailure或者onResponse方法内部执行call.cancel()都可以。如果想取消所有的请求,则可以okhttpclient.dispatcher().cancelAll();

二、OkHttp简单使用

1. 进行get请求

/**
 * 原始的get请求
 * 
 * @author 吴晓畅
 *
 */
public class OkHttpGet {

    public void get() {

         //1.okhttpClient对象
        OkHttpClient okHttpClient = new OkHttpClient.Builder().
                //在这里,还可以设置数据缓存等
                //设置超时时间
                connectTimeout(15, TimeUnit.SECONDS).
                readTimeout(20, TimeUnit.SECONDS).
                writeTimeout(20,  TimeUnit.SECONDS).
                //错误重连  
                retryOnConnectionFailure(true).
                build();

        //2构造Request,
        //builder.get()代表的是get请求,url方法里面放的参数是一个网络地址
        Request.Builder builder = new Request.Builder();

        Request request = builder.get().url("http://www.baidu.com/").build();

        //3将Request封装成call
        Call call = okHttpClient.newCall(request);

        //4,执行call,这个方法是异步请求数据
        call.enqueue(new Callback() {

            @Override
            public void onFailure(Call arg0, IOException arg1) {

                //失败调用
            }

            @Override
            //由于OkHttp在解析response的时候依靠的是response头信息当中的Content-Type字段来判断解码方式
            //OkHttp会使用默认的UTF-8编码方式来解码
            //这里使用的是异步加载,如果需要使用控件,则在主线程中调用
            public void onResponse(Call arg0, Response arg1) throws IOException {

                 //成功调用

            }
        });

    }
}

2. 进行post请求

/**
 * 使用okhttp进行post请求
 * 
 * @author 吴晓畅
 *
 */
public class OkHttpPost {

    public void initPost() {

        //1.okhttpClient对象
        OkHttpClient okHttpClient = new OkHttpClient.Builder().
                //在这里,还可以设置数据缓存等
                //设置超时时间
                connectTimeout(15, TimeUnit.SECONDS).
                readTimeout(20, TimeUnit.SECONDS).
                writeTimeout(20,  TimeUnit.SECONDS).
                //错误重连  
                retryOnConnectionFailure(true).
                build();

         RequestBody requestBodyPost = new FormBody.Builder()
         .add("page", "1")
         .add("code", "news")
         .add("pageSize", "20")
         .add("parentid", "0")
         .add("type", "1")
         .build();

         Request requestPost = new Request.Builder()
         .url("www.baidu.com")
         .post(requestBodyPost)
         .build();

         okHttpClient.newCall(requestPost).enqueue(new Callback() {

            @Override
            public void onFailure(Call arg0, IOException arg1) {
                // TODO Auto-generated method stub

            }

            @Override
            public void onResponse(Call arg0, Response arg1) throws IOException {

                //okHttp还支持GJson的处理方式
                //在这里可以进行List<bean>和bean处理

            }

         });

 }

}

3. 进行图片上传和下载

/**
 * 使用OkHttp进行图片上传和下载
 * 
 * @author 吴晓畅
 *
 */
public class OkHttpPicture 
{

    public void getPicture() {

         //1.创建一个okhttpclient对象  
         OkHttpClient okHttpClient = new OkHttpClient();  

         //2.创建Request.Builder对象,设置参数,请求方式如果是Get,就不用设置,默认就是Get  
         Request request = new Request.Builder()  
                .url("www.baidu.com")  
                .build();  

         //3.创建一个Call对象,参数是request对象,发送请求  
         Call call = okHttpClient.newCall(request);  

         //4.异步请求,请求加入调度  
         call.enqueue(new Callback() {

            @Override
            public void onFailure(Call arg0, IOException arg1) {
                // TODO Auto-generated method stub

            }

            @Override
            public void onResponse(Call arg0, Response arg1) throws IOException {

//              //得到从网上获取资源,转换成我们想要的类型  
//                byte[] Picture_bt = response.body().bytes();  
//                //通过handler更新UI  
//                Message message = handler.obtainMessage();  
//                message.obj = Picture_bt;  
//                message.what = SUCCESS;  
//                handler.sendMessage(message);  

            } 

        });  

    }

    public void shangChuanPicture() {

        OkHttpClient mOkHttpClent = new OkHttpClient();

        //获取sd卡中的文件
        File file = new File(Environment.getExternalStorageDirectory()+"/HeadPortrait.jpg");

        MultipartBody.Builder builder = new MultipartBody.Builder()
                //设置类型
                .setType(MultipartBody.FORM)
                //设置正文内容
                .addFormDataPart("img", "HeadPortrait.jpg",
                        RequestBody.create(MediaType.parse("image/png"), file));

        RequestBody requestBody = builder.build();

        Request request = new Request.Builder()
                .url("www.baidu.com")
                .post(requestBody)
                .build();

        Call call = mOkHttpClent.newCall(request);

    }
}

3. 拦截器使用

什么是拦截器
首先我们需要了解什么事拦截器。打个比方,镖局押着一箱元宝在行走在一个山间小路上,突然从山上下来一群山贼拦住了镖局的去路,将镖局身上值钱的东西搜刮干净后将其放行。其中山贼相当于拦截器,镖局相当于一个正在执行任务的网络请求,请求中的参数就是镖局携带的元宝。拦截器可以将网络请求携带的参数进行修改验证,然后放行。这里面其实设计了AOP编程的思想(面向切面编程)。
在介绍拦截器的作用和好处之前,我们还是要回到山贼这个角色上,如果让你做一次山贼,你会在什么地方埋伏?肯定是在镖局必经之路上埋伏。也就是说,拦截器就是在所有的网络请求的必经之地上进行拦截。
(1)拦截器可以一次性对所有的请求和返回值进行修改。
(2)拦截器可以一次性对请求的参数和返回的结果进行编码,比如统一设置为UTF-8.
(3)拦截器可以对所有的请求做统一的日志记录,不需要在每个请求开始或者结束的位置都添加一个日志操作。
(4)其他需要对请求和返回进行统一处理的需求….

OkHttp中拦截器分类
OkHttp中的拦截器分2个:APP层面的拦截器(Application Interception)、网络请求层面的拦截器(Network Interception)
(1)Application Interceptor是在请求执行刚开始,还没有执行OkHttp的核心代码前进行拦截,Application拦截器的作用:
1)不需要担心是否影响OKHttp的请求策略和请求速度。
2)即使是从缓存中取数据,也会执行Application拦截器。
3)允许重试,即Chain.proceed()可以执行多次。(当然请不要盲目执行多次,需要加入你的逻辑判断)
(2)Network Interception是在连接网络之前
1)可以修改OkHttp框架自动添加的一些属性(当然最好不要修改)。
2)可以观察最终完整的请求参数(也就是最终服务器接收到的请求数据和熟悉)

使用注意点
如果对拦截器不是很熟的同学,开发过程中,建议使用Application Interception。这样避免对OkHttp请求策略的破坏。

常见实际场景
(1)对请求参数进行统一加密处理。
(2)拦截不符合规则的URL。
(3)对请求或者返回参数设置统一的编码方式
(4)其它…。

代码实操

public class OkHttpLanJieQi {

    /**
     * 应用拦截器
     */
    Interceptor appInterceptor = new Interceptor() {
        @Override
        public Response intercept(Chain chain) throws IOException {

            Request request = chain.request();

            //———请求之前要做的事情————
            HttpUrl url = request.url();
            String s = url.url().toString();

            Response response = chain.proceed(request);

            //———请求之后要做事情————
            Log.d("aa","app interceptor:begin");

            return response;

        }

    };

    /**
     * 网络拦截器
     */
    Interceptor networkInterceptor = new Interceptor() {
        @Override
        public Response intercept(Chain chain) throws IOException {
            Request request = chain.request();

            //———请求之前要做的事情————

            Response  response = chain.proceed(request);

          //———请求之后要做事情————

            return response;
        }
    };

    /**
     * 进行get请求,并配置拦截器
     */
    public void initGet() {

        OkHttpClient okHttpClient = new OkHttpClient
                .Builder()
                .addInterceptor(appInterceptor)//Application拦截器
                .addNetworkInterceptor(networkInterceptor)//Network拦截器
                .build();

        //2构造Request,
        //builder.get()代表的是get请求,url方法里面放的参数是一个网络地址
        Request.Builder builder = new Request.Builder();

        Request request = builder.get().url("http://www.baidu.com/").build();

        //3将Request封装成call
        Call call = okHttpClient.newCall(request);

        //4,执行call,这个方法是异步请求数据
        call.enqueue(new Callback() {

            @Override
            public void onFailure(Call arg0, IOException arg1) {

                //失败调用
            }

            @Override
            //由于OkHttp在解析response的时候依靠的是response头信息当中的Content-Type字段来判断解码方式
            //OkHttp会使用默认的UTF-8编码方式来解码
            //这里使用的是异步加载,如果需要使用控件,则在主线程中调用
            public void onResponse(Call arg0, Response arg1) throws IOException {

                 //成功调用

            }
        });

    }

}

三、OkHttp封装

1. 自行简单封装

/**
 * okhttp操作进行封装
 * 
 * @author 吴晓畅
 *
 */
public class OkHttp {

    public void get(String url, Callback callback) {

        //1.okhttpClient对象
        OkHttpClient okHttpClient = new OkHttpClient.Builder().
                //在这里,还可以设置数据缓存等
                //设置超时时间
                connectTimeout(15, TimeUnit.SECONDS).
                readTimeout(20, TimeUnit.SECONDS).
                writeTimeout(20,  TimeUnit.SECONDS).
                addInterceptor(appInterceptor).//Application拦截器
                //错误重连  
                retryOnConnectionFailure(true).
                build();

        //2构造Request,
        //builder.get()代表的是get请求,url方法里面放的参数是一个网络地址
        Request.Builder builder = new Request.Builder();

        Request request = builder.get().url(url).build();

        //3将Request封装成call
        Call call = okHttpClient.newCall(request);

        //4,执行call,这个方法是异步请求数据
        call.enqueue(callback);

    }

    public void post(String url, List<String> list, Callback callback, RequestBody requestBody) {

        //1.okhttpClient对象
        OkHttpClient okHttpClient = new OkHttpClient.Builder().
                //在这里,还可以设置数据缓存等
                //设置超时时间
                connectTimeout(15, TimeUnit.SECONDS).
                addInterceptor(appInterceptor).//Application拦截器
                readTimeout(20, TimeUnit.SECONDS).
                writeTimeout(20,  TimeUnit.SECONDS).
                //错误重连  
                retryOnConnectionFailure(true).
                build();

         RequestBody requestBodyPost = requestBody;

         Request requestPost = new Request.Builder()
         .url(url)
         .post(requestBodyPost)
         .build();

         okHttpClient.newCall(requestPost).enqueue(callback);

    }

    /**
     * 应用拦截器
     */
    Interceptor appInterceptor = new Interceptor() {
        @Override
        public Response intercept(Chain chain) throws IOException {

            Request request = chain.request();

            //———请求之前要做的事情————

            Response response = chain.proceed(request);

            //———请求之后要做事情————

            return response;

        }

    };
}

2. Android--OKHttpUtils框架封装

简介
OKHttpUtils:一个专注于让网络请求更简单的网络请求框架,对于任何形式的网络请求只需要一行代码。它是OKHttp的一次二次封装,封装的目的是让网络请求更加方便。

OKHttpUtils优势
(1)性能高,使用主流的okhttp的进行封装
OKHttp我们知道它支持http2和socket的重连。自动选择最好的路线,拥有自己维护socket维护的连接池。可以减少TCP的握手次数,同时它拥有队列线程池可以轻松的并发请求。
(2)特有的网络缓存模式
OKHttpUtils是大多数网络框架不具备的,比如我们公司的网络老板要求不仅在有网的情况下,进行展示网络数据,在无网的情况下使用缓存数据。这时候我们使用普通网络请求,就需要大量的判断。当前是否有网和无网状态,根据不同的状态保存不同的数据。然后再决定是否使用缓存。但是这是一个通用的写法。于是OKHttpUtils使用自动网络缓存模式。让用户只关注数据处理。
(3)方便易用的扩展接口
可以添加全局的公共参数、全局的拦截器、全局的超时时间,更可以对单个请求定制拦截器。请求参数修改等等。
(4)强大的Cookie的保存策略
在客户端对Cookie的获取不是一个特别简单的事情,Cookie全程自动管理,并且提供了额外的Cookie管理方法,引入额外的自动管理中,添加任何你想创建的Cookie。

依赖包导入

compile 'com.zhy:okhttputils:2.0.0'

进行get请求

    private String get(String url) throws IOException {

      Request request = new Request.Builder()

          .url(url)//传url

          .build();//创建

      //把request传进client
      //execute()执行线程
      Response response = client.newCall(request).execute();

      return response.body().string();
    }

进行post请求

    private String post(String url, String json) throws IOException {
        RequestBody body = RequestBody.create(JSON, json);
        Request request = new Request.Builder()
            .url(url)
            .post(body)
            .build();
        Response response = client.newCall(request).execute();
        return response.body().string();
    }

使用okhttp-utils请求单张图片

public void getImage()
        {
         tv_result.setText("");
            String url = "http://images.csdn.net/20150817/1.jpg";
            OkHttpUtils
                    .get()//
                    .url(url)//
                    .tag(this)//
                    .build()//
                    .connTimeOut(20000)//链接超时
                    .readTimeOut(20000)//读取超时
                    .writeTimeOut(20000)//写入超时
                    .execute(new BitmapCallback()
                    {
                        @Override
                        public void onError(Call call, Exception e, int id)
                        {
                            tv_result.setText("onError:" + e.getMessage());
                        }

                        @Override
                        public void onResponse(Bitmap bitmap, int id)
                        {
                            Log.e("TAG", "onResponse:complete");
                            iv_icon.setImageBitmap(bitmap);
                        }
                    });
        }

使用okhttp-utils上传多个或者单个文件

 /**
      * 使用okhttp-utils上传多个或者单个文件
      */     
     public void multiFileUpload()
        {

         //FileUploadServlet
         String mBaseUrl = "http://192.168.3.27:8080/FileUpload/FileUploadServlet";

            File file = new File(Environment.getExternalStorageDirectory(), "tupian.jpg");
            File file2 = new File(Environment.getExternalStorageDirectory(), "zanghao.jpg");
            if (!file.exists())
            {
                Toast.makeText(OKHttpActivity.this, "文件不存在,请修改文件路径", Toast.LENGTH_SHORT).show();
                return;
            }
//          Map<String, String> params = new HashMap<String, String>();
//          params.put("username", "黄敏莹");
//          params.put("password", "123");

            String url = mBaseUrl;
            OkHttpUtils.post()//
                    .addFile("mFile", "server_tupian.jpg", file)//
                    .addFile("mFile", "server_zanghao.jpg", file2)//两个addFile就是多文件上传,注释掉一个就是单文件上传
                    .url(url)
//                  .params(params)//
                    .build()//
                    .execute(new MyStringCallBack());//回调
        }

回调处理

/**
     * 用于回调
     * @author Mloong
     *
     */
    private class MyStringCallBack extends StringCallback{

        @Override
        public void onBefore(Request request, int id) {
            // TODO Auto-generated method stub
            super.onBefore(request, id);

            setTitle("loading...");
        }

        @Override
        public void onAfter(int id) {
            // TODO Auto-generated method stub
            super.onAfter(id);

            setTitle("sample-okhttp");
        }

        //出错
        @Override
        public void onError(Call arg0, Exception e, int arg2) {

            e.printStackTrace();

            tv_result.setText("onError:"+e.getMessage());

        }

        //成功后回调
        @Override
        public void onResponse(String response, int id) {

            //显示文本信息
            tv_result.setText("onResponse:"+ response);

            switch (id) {
            case 100:

                Toast.makeText(OKHttpActivity.this, "http", Toast.LENGTH_LONG).show();

                break;

            case 101:

                Toast.makeText(OKHttpActivity.this, "https", Toast.LENGTH_LONG).show();

                break;

            default:
                break;
            }

        }

        @Override
        public void inProgress(float progress, long total, int id) {

            Log.e(TAG, "inProgress:"+progress);

            mProgressBar.setProgress((int) (100*progress));

        }

    }

四、项目源码下载

链接:https://pan.baidu.com/s/1f3eZhmfKakrd9zaGzX8_gQ
密码:cv4b

关于okhttp的全部学习内容,我们这边都有系统的知识体系以及进阶视频资料,有需要的朋友可以加群免费领取安卓进阶视频教程,源码,面试资料,群内有大牛一起交流讨论技术;818520403
(包括自定义控件、NDK、架构设计、混合式开发工程师(React native,Weex)、性能优化、完整商业项目开发等)

Android高级进阶视频教程
相关文章
|
23小时前
|
缓存 Java 测试技术
【01】噩梦终结flutter配安卓android鸿蒙harmonyOS 以及next调试环境配鸿蒙和ios真机调试环境-flutter项目安卓环境配置-gradle-agp-ndkVersion模拟器运行真机测试环境-本地环境搭建-如何快速搭建android本地运行环境-优雅草卓伊凡-很多人在这步就被难倒了
【01】噩梦终结flutter配安卓android鸿蒙harmonyOS 以及next调试环境配鸿蒙和ios真机调试环境-flutter项目安卓环境配置-gradle-agp-ndkVersion模拟器运行真机测试环境-本地环境搭建-如何快速搭建android本地运行环境-优雅草卓伊凡-很多人在这步就被难倒了
13 3
【01】噩梦终结flutter配安卓android鸿蒙harmonyOS 以及next调试环境配鸿蒙和ios真机调试环境-flutter项目安卓环境配置-gradle-agp-ndkVersion模拟器运行真机测试环境-本地环境搭建-如何快速搭建android本地运行环境-优雅草卓伊凡-很多人在这步就被难倒了
|
4天前
|
JavaScript 搜索推荐 Android开发
【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
23 8
【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
|
14天前
|
Dart 前端开发 Android开发
【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
37 4
【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
|
16天前
|
前端开发 Java Shell
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
119 20
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
|
29天前
|
缓存 前端开发 Android开发
【04】flutter补打包流程的签名过程-APP安卓调试配置-结构化项目目录-完善注册相关页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程
【04】flutter补打包流程的签名过程-APP安卓调试配置-结构化项目目录-完善注册相关页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程
79 12
【04】flutter补打包流程的签名过程-APP安卓调试配置-结构化项目目录-完善注册相关页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程
|
6月前
|
移动开发 搜索推荐 Android开发
安卓与iOS开发:一场跨平台的技术角逐
在移动开发的广阔舞台上,两大主角——安卓和iOS,持续上演着激烈的技术角逐。本文将深入浅出地探讨这两个平台的开发环境、工具和未来趋势,旨在为开发者揭示跨平台开发的秘密,同时激发读者对技术进步的思考和对未来的期待。
|
6月前
|
安全 Android开发 Swift
安卓与iOS开发:平台差异与技术选择
【8月更文挑战第26天】 在移动应用开发的广阔天地中,安卓和iOS两大平台各占一方。本文旨在探索这两个系统在开发过程中的不同之处,并分析开发者如何根据项目需求选择合适的技术栈。通过深入浅出的对比,我们将揭示各自平台的优势与挑战,帮助开发者做出更明智的决策。
104 5
|
6月前
|
移动开发 开发工具 Android开发
安卓与iOS开发之巅:探索两大移动平台的核心技术与创新趋势
【8月更文挑战第22天】 在移动应用开发的浩瀚星海中,安卓和iOS犹如两颗璀璨的星辰,各自绽放着独特的光芒。本文将深入剖析这两大平台的技术架构、开发工具、生态系统以及未来发展趋势,带领读者领略它们的魅力所在。无论你是安卓的忠实拥趸,还是iOS的铁杆粉丝,亦或是中立的开发者,这篇文章都将为你揭示一个多元而精彩的移动开发世界。让我们一起踏上这场技术之旅,感受安卓与iOS之间的碰撞与融合,共同见证移动开发的未来。
82 0
|
6月前
|
移动开发 开发工具 Android开发
探索安卓与iOS开发的差异:技术选择的影响
【8月更文挑战第17天】 在移动应用开发的广阔天地中,安卓和iOS两大平台各领风骚。本文通过比较这两个平台的编程语言、开发工具及市场策略,揭示了技术选择对开发者和产品成功的重要性。我们将从开发者的视角出发,深入探讨不同平台的技术特性及其对项目实施的具体影响,旨在为即将步入移动开发领域的新手提供一个清晰的指南,同时给予资深开发者新的思考角度。
78 3
|
6月前
|
编解码 Android开发 iOS开发
安卓与iOS开发:平台差异下的技术创新之路
在数字时代的浪潮中,移动应用开发如同两股潮流——安卓与iOS,各自携带着独特的技术生态和文化基因。本文将深入探讨这两大平台的开发环境、编程语言和工具的差异,以及它们如何塑造了不同的用户体验和技术趋势。通过比较分析,我们旨在揭示跨平台开发的可能性和挑战,同时探索未来技术创新的方向。让我们一起跟随代码的足迹,穿越安卓的开放草原和iOS的精密园林,发现那些隐藏在平台差异之下的创新机遇。
53 1

热门文章

最新文章

  • 1
    如何修复 Android 和 Windows 不支持视频编解码器的问题?
  • 2
    Android历史版本与APK文件结构
  • 3
    【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
  • 4
    【04】flutter补打包流程的签名过程-APP安卓调试配置-结构化项目目录-完善注册相关页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程
  • 5
    当flutter react native 等混开框架-并且用vscode-idea等编译器无法打包apk,打包安卓不成功怎么办-直接用android studio如何打包安卓apk -重要-优雅草卓伊凡
  • 6
    APP-国内主流安卓商店-应用市场-鸿蒙商店上架之必备前提·全国公安安全信息评估报告如何申请-需要安全评估报告的资料是哪些-优雅草卓伊凡全程操作
  • 7
    【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
  • 8
    Android经典面试题之Kotlin中Lambda表达式和匿名函数的区别
  • 9
    【02】仿站技术之python技术,看完学会再也不用去购买收费工具了-本次找了小影-感觉页面很好看-本次是爬取vue需要用到Puppeteer库用node.js扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
  • 10
    【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
  • 1
    Cellebrite UFED 4PC 7.71 (Windows) - Android 和 iOS 移动设备取证软件
    24
  • 2
    【03】仿站技术之python技术,看完学会再也不用去购买收费工具了-修改整体页面做好安卓下载发给客户-并且开始提交网站公安备案-作为APP下载落地页文娱产品一定要备案-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
    33
  • 3
    Android历史版本与APK文件结构
    121
  • 4
    【02】仿站技术之python技术,看完学会再也不用去购买收费工具了-本次找了小影-感觉页面很好看-本次是爬取vue需要用到Puppeteer库用node.js扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
    29
  • 5
    【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
    23
  • 6
    APP-国内主流安卓商店-应用市场-鸿蒙商店上架之必备前提·全国公安安全信息评估报告如何申请-需要安全评估报告的资料是哪些-优雅草卓伊凡全程操作
    57
  • 7
    【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
    37
  • 8
    当flutter react native 等混开框架-并且用vscode-idea等编译器无法打包apk,打包安卓不成功怎么办-直接用android studio如何打包安卓apk -重要-优雅草卓伊凡
    73
  • 9
    【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
    119
  • 10
    Android经典面试题之Kotlin中Lambda表达式和匿名函数的区别
    29