Android基础学习(十七)—— Retrofit

2023-11-10

Retrofit本身并没有提供网络访问的能力,但是它底层封装了OkHttp,也是由Square公司贡献的一个处理网络请求的开源项目

A type-safe HTTP client for Android and Java

https://github.com/square/retrofit

Retrofit的基本使用
Retrofit中的注解
文件上传与下载
Retrofit 嵌套请求与适配器
Retrofit的转换器


一、Retrofit的基本使用

在项目模块的build.gradle中添加依赖:

implementation 'com.squareup.retrofit2:retrofit:2.9.0'

(示例)服务器接口信息:

服务器域名:https://www.httpbin.org/

接口:post
参数:username, password

接口:get
参数:username, password

(1)根据HTTP接口创建 Java 接口

import okhttp3.ResponseBody;  //注意这里是okhttp3的包
import retrofit2.Call;
import retrofit2.Response;
import retrofit2.http.POST
import retrofit2.http.GET

public interface HttpbinService{
 
    @GET("get")
    Call<ResponseBody> get(@Query("username") String username, @Query("password") String pwd);
    
    
    @POST("post")
    @FormUrlEncoded 
    Call<ResponseBody> postForm(@Field("username") String username, @Field("password") String pwd);
}

(2)创建Retrofit对象,并生成接口实现类对象

Retrofit retrofit = new Retrofit.Builder().baseUrl("https://www.httpbin.org/").build();
HttpbinService httpbindService = retrofit.create(HttpbinService.class);

(3)接口实现类对象调用对应方法获得响应

retrofit2.Call<ResponseBody> call = httpbindService.post("lance", "123");
call.enqueue(new retrofit2.Call<ResponseBody> call, retrofit2.Response<ResponseBody> response){

    @Override
    public void onResponse(retrofit2.Call<ResponseBody> call, retrofit2.Response<ResponseBody> response){
        Log.i(TAG, "postAsync::" + response.body().string());
    }
    
    @Override
    public void onFailure(retrofit2.Call<ResponseBody> call, Throwable t){
        
    }
});

相对于OkHttp来说,Retrofit的使用较为简洁


二、Retrofit中的注解

  • 方法注解:@GET, @POST, @PUT, @DELETE, @PATH, @HEAD, @OPTIONS, @HTTP
  • 标记注解:@FormUrlEncoded, @Multipart, @Streaming
  • 参数注解:@Query, @QueryMap, @Body, @Field, @FieldMap, @Part, @PartMap
  • 其他注解:@Path, @Header, @Headers, @Url

1、方法注解

(1)@GET

​ get网络请求

代码示例:

一个简单的get请求

baseURL: http://102.10.10.132/api

请求网址: http://102.10.10.132/api/News

@GET("News")
Call<NewsBean> getItem();

(2)@POST

(3)@PUT

(4)@DELETE

(5)@PATH

(6)@HEAD

(7)@OPTIONS

(8)@HTTP


2、标记注解

(1)@FormUrlEncoded

用于修饰 @Field注解 和 @FieldMap 注解,将会自动将请求参数的类型调整为 application/x-www-form-urlencoded

(2)@Multipart

(3)@Streaming


3、参数注解

(1)@Query

主要用于 Get 请求数据,用于拼接 Url 路径后面的查询参数,一个 @Query 相当于拼接一个参数,多个参数中间用 “,” 隔开。

参数以 “?key1=value1&key2=value2” 的形式拼接在Url的后面。

在Post请求中,尽量不要使用 @Query 和 @QueryMap,因为它传入的参数是直接拼接在 url 上的,不安全,而 @Field 和 @FieldMap 是写入到 Body 中的。

示例:

baseUrl为:http://mock-api.com/2vKVbXK8.mock/

访问地址:http://mock-api.com/2vKVbXK8.mock/api/getUserInfo?id=1234

@GET("api/getUserInfo")
Call<UserInfo> getUserInfo(@Query("id") String userId);

(2)@QueryMap

效果等同于多个@Query参数拼接,主要也用于Get请求网络数据。

示例:

baseUrl为:http://mock-api.com/2vKVbXK8.mock/

访问地址:http://mock-api.com/2vKVbXK8.mock/api/getArticalInfo?id=405&page=1

@GET("api/getArticalInfo")
Call<ArticalInfo> getArticalInfo(@QueryMap Map<String, String> params);
Map<String, String> params = new HashMap<>();
params.put("id", "405");
params.put("page", "1");

getApi.getArticalInfo(params).enqueue(new Callback<ArticalInfo>() {
    @Override
    public void onResponse(Call<ArticalInfo> call, Response<ArticalInfo> response) {
        if (response != null && response.body() != null) {
            Log.i(TAG, "onRespons:" + response.body().toString());
        }
    }
    @Override
    public void onFailure(Call<ArticalInfo> call, Throwable t) {
        Log.i(TAG, "onFailure: " + t);
    }
});

(3)@Body

请求参数中含多个不同类型

如果使用多个 @Field 较为繁琐

使用 @Body 注解,可直接传入一个对象,对象中可包含多种类型的数据

访问地址:http://mock-api.com/2vKVbXK8.mock/api/bodyParam

代码示例:

@POST("api/bodyParam")
Call<ResponseBody> postBodyFun(@Body PostBodyBean postBodyBean);
public class PostBodyBean {
    private String key;
    private int num;
    private boolean isTrue;
}
PostBodyBean postBodyBean = new PostBodyBean("myfittinglife",1,true);
postApi.postBodyFun(postBodyBean).enqueue(new Callback<ResponseBody>() {
    @Override
    public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) 	{
        try {
            String str = new String(response.body().bytes());
            Log.i(TAG, "onResponse: " + str);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    @Override
    public void onFailure(Call<ResponseBody> call, Throwable t) {
        Log.i(TAG, "onFailure: " + t);        
    }
});

其中,不一定要自定义PostBodyBean类,可以使用系统的FormBody

FormBody formBody = new FormBody.Builder()
    .add("a", "1")
    .add("b", "2")
    .build();

注意:

使用@Body注解一定在创建Retrofit的时候加上.addConverterFactory(GsonConverterFactory.create()),目的是将对象转化为json字符串进行传递,否则会报以下错误

Unable to create @Body converter for class PostBodyBean

(4)@Field

用于 Post 请求,对应于 GET 请求中的 @Query

访问地址:http://mock-api.com/2vKVbXK8.mock/api/fieldParam

@FormUrlEncoded
@POST("api/fieldParam")
Call<ResponseBody> postFieldFun(@Field("key") String key);
private PostApi postApi;
postApi = retrofit.create(PostApi.class);

postApi.postFieldFun("myfittinglife").enqueue(new Callback<ResponseBody>() {
    @Override
    public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) 	{
        try {
            String str = new String(response.body().bytes());
            Log.i(TAG, "onResponse: " + str);           
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    @Override
    public void onFailure(Call<ResponseBody> call, Throwable t) {
        Log.i(TAG, "onFailure: " + t);
    }
});

key = myfittinglife

(5)@FieldMap

用于Post请求,对应于 GET 请求中的 @QueryMap

适合多个相同类型参数的传递

访问地址:http://mock-api.com/2vKVbXK8.mock/api/fieldMapParam

@FormUrlEncoded
@POST("api/fieldMapParam")
Call<ResponseBody> postFildMapFun(@FieldMap Map<String, String> params);
Map<String, String> params = new HashMap<>();
params.put("key", "myfittinglife");
params.put("password", "123456");

postApi.postFildMapFun(params).enqueue(new Callback<ResponseBody>() {
    @Override
    public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) 	{
        try {
            String str = new String(response.body().bytes());
            Log.i(TAG, "onResponse: " + str);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    @Override
    public void onFailure(Call<ResponseBody> call, Throwable t) {
        Log.i(TAG, "onFailure: " + t);       
    }
});

(6)@Part

(7)@PartMap

“@Part” 和 “@PartMap” 是结合标记注解 “@Multipart“ 一起使用的,和文件上传相关


4、其他注解

(1)@Path

主要用于Get请求,用于替换Url路径中的变量字符

代码示例:

baseUrl为:http://mock-api.com/2vKVbXK8.mock/

访问地址:

http://mock-api.com/2vKVbXK8.mock/api/getDynamicInfo/1/data

http://mock-api.com/2vKVbXK8.mock/api/getDynamicInfo/2/data

@GET("api/getDynamicInfo/{param}/data")
Call<ResponseBody> getDynamicInfo(@Path("param")int paramValue);

该方法通过 GET 请求去访问服务器的 http://mock-api.com/2vKVbXK8.mock/api/getDynamicInfo/{param}/data,其中会通过 @Path 注解,将路径中的 {param} 替换成参数 param 的具体值。

(2)@Header

动态添加单个头部信息

示例:

baseUrl为:http://mock-api.com/2vKVbXK8.mock/

访问地址:http://mock-api.com/2vKVbXK8.mock/api/dynamicHeadersInfo

@GET("api/dynamicHeadersInfo")
Call<ResponseBody> getDynamicHeaderInfo(@Header("version") String version);
getApi.getDynamicHeaderInfo("1.1.1").enqueue(new Callback<ResponseBody>() {
    @Override
    public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) 	{
    }
    @Override
    public void onFailure(Call<ResponseBody> call, Throwable t) {        
    }
});

(3)@Headers

静态添加头部信息:包含添加单个头部、添加多个头部。注解内部以 key:value 的方式填写内容

示例:

baseUrl为:http://mock-api.com/2vKVbXK8.mock/

访问地址:http://mock-api.com/2vKVbXK8.mock/api/staticHeaderInfo

1)静态添加单个头部

@Headers("version:1.1")
@GET("api/staticHeaderInfo")
Call<GetBean> getStaticHeadersInfo();

2)静态添加多个头部

@Headers({"version:1.1",
            "type:android"})
@GET("api/staticHeadersInfo")
Call<GetBean> getStaticMoreHeadersInfo();

(4)HeaderMap

动态添加多个头部信息

示例:

baseUrl为:http://mock-api.com/2vKVbXK8.mock/

访问地址:http://mock-api.com/2vKVbXK8.mock/api/dynamicHeadersInfo

@GET("api/dynamicHeadersInfo")
Call<ResponseBody> getDynamicHeadersInfo(@HeaderMap Map<String, String> headers);
Map<String, String> headers = new HashMap<>();
headers.put("version", "2.2.2");
headers.put("type", "Android");

getApi.getDynamicHeadersInfo(headers).enqueue(new Callback<ResponseBody>() {
    @Override
    public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) 	{
    }
    @Override
    public void onFailure(Call<ResponseBody> call, Throwable t) {
    }
});
}

(5)@Url

当要访问的地址不只是动态的变几个参数,而是整个地址都要变化,甚至是基类地址也要变化时,这种动态地址就要用到@Url注解

代码示例:

@GET
Call<ResponseBody> getDynamicUrl(@Url String url);
String url = "http://mock-api.com/2vKVbXK8.mock/api/getDynamicUrlData"
    
getApi.getDynamicUrl(url).enqueue(new Callback<ResponseBody>() {
    @Override
    public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) 	{
        try {
            String str = new String(response.body().bytes());
            Log.i(TAG, "onResponse: " + str);

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    @Override
    public void onFailure(Call<ResponseBody> call, Throwable t) {
        Log.i(TAG, "onFailure: " + t);
    }
});    

所以说这个注解很方便,链接可通过此注解传入完整的Url进行访问。

注意

虽然说最终访问的地址与原先的baseUrl无关,但是baseUrl还是要以http://https://开头,并且后面至少要跟一个字母或者其他东西,不然就会报错。

1)报错写法

http://

写成上面的内容会报错,Invalid URL host: ""错误。

2)无报错写法

http://a

不会报错,这个a这里写什么都可以,没有以/结尾也可以


三、文件上传与下载

1、上传文件:

public interface UploadService{
    @POST("post")
    @Multipart
    Call<ResponseBody> upload(@Part MultipartBody.Part file);
}   //多个文件可用PartMap
public class UploadFileUnitTest{
    Retrofit retrofit = new Retrofit.Builder().baseUrl("https://www.httpbin.org/").build();
    UploadService uploadService = retrofit.create(UploadService.class);
    
    public void uploadFileTest() throw IOException{
        File file1 = new File("C:\\Users\\Administrator\\Desktop\\1.txt");
        MultipartBody.Part part =  MultipartBody.Part.createFormData("file1", "1.txt", RequestBody.create(file1, MediaType.parse("text/plain")));
        
        Call<ResponseBody> call = uploadService.upload(part);
        System.out.println(call.execute().body().string());
    }
}

2、下载文件:

找一个下载链接

添加下载接口

public interface UploadService{
    @POST("post")
    @Multipart
    Call<ResponseBody> upload(@Part MultipartBody.Part file);
    
    @GET
    Call<ResponseBody> download(@Url string url);
    
    @GET
    Flowable<ResponseBody> downloadRxJava(@Url string url);
}

先学会基本使用,然后了解框架原理,接着学习完成自定义适配器等等

public class UploadFileUnitTest{
    ...
    public void downloadTest(){
        Response<ResponseBody> response = uploadService.download("下载链接(自己随便找一个)").execute();
        //if response.isSuccessful()
        InputStream inputStream = response.body().byteStream();  //试试string()呢?
        FileOutputStream fos = new FileOutputStream("C:\\Users\\Administrator\\Desktop\\a.apk");
        int len;
        byte[] buff = new byte[4096];
        while((len = inputStream.read(buffer)) != -1){
            //继续读
            
            fos.write(buffer, 0, len);
        }
        fos.close();
        inputStream.close();
    }
    
    
    public void downloadRxjavaTest(){
        uploadService.downloadRxJava("下载链接(自己随便找一个)")
            .map(new Function<ResponseBody, File>()){
            @Override
            public File apply(ResponseBody responseBody) throws Throwable{
                InputStream inputStream = responseBody.byteStream();
                
                //if response.isSuccessful()
                InputStream inputStream = response.body().byteStream();  //试试string()呢?
                File file = new File("C:\\Users\\Administrator\\Desktop\\a.apk");
                FileOutputStream fos = new FileOutputStream(file);
                int len;
                byte[] buff = new byte[4096];
                while((len = inputStream.read(buffer)) != -1){
                    //继续读

                    fos.write(buffer, 0, len);
                }
                fos.close();
                inputStream.close();
                
                return file;
            }
        }).subscribe(new Consumer<File>(){
        	@Override
            public void accept(File file) throws Throwable{
                
            }
        });
        while(true){
            
        }
    }
}

还有需要注意的一点,如果下载的文件特别大,则在写Java接口时,需加上 “@Streaming" 注解,:

public interface UploadService{
    @POST("post")
    @Multipart
    Call<ResponseBody> upload(@Part MultipartBody.Part file);
    
    @Streaming
    @GET
    Call<ResponseBody> download(@Url string url);
    
    @Streaming
    @GET
    Flowable<ResponseBody> downloadRxJava(@Url string url);
}

在下载文件中,“@Streaming” 注解非常关键,可以有效避免内存溢出的问题,该注解表示以流的方式获取文件数据。


四、Retrofit 嵌套请求与适配器

1、Retrofit的嵌套请求

在实际开发中,可能会存在:需要先请求A接口,再请求B接口的情况。比如需要请求获取收藏文章列表,但是需要先登录拿到Cookie才能请求收藏文章列表接口。此时请求就有了先后顺序,为了完成这个功能,我们需要这样实现代码:

//先登录
Call<BaseResponse> call = wanAndroidService2.login("lanceedu", "123123");
call.enqueue(new Callback<BaseResponse>(){
   @Override
    public void onResponse(Call<BaseResponse> call, Response<BaseResponse) response){
        //登录成功请求收藏的文章
        if(response.isSuccessful()){
            wanAndroidService2.getArticle(0).enqueue(new Callback<ResponseBody>(){
                @Override
                public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response){
                    
                }
                
                @Override
                public void onFailure(Call<ResponseBody> call, Throwable t){
                    
                }
            });
        }
    }
    
    @Override
    public void onFailure(Call<BaseResponse> call, Throwable t){
        
    }
});

2、Retrofit的适配器

Retrofit的接口方法返回类型必须是Call,如果能够将Call改为RxJava中的Observable,对于嵌套的情况,就能得到非常方便优雅的解决。这就是适配器的功能,如果我们想要返回的不是Call,适配器就能帮助我们转换为其它类型。

以RxJava3为例:

添加依赖:

implementation 'com.squareup.retrofit2:adapter-rxjava3:2.9.0'

修改接口方法:

@POST("post")
@FormUrlEncoded
Observable<JavaBean> post(@Field("username") String userName, @Field("password")String pwd);

在项目中:

implementation 'com.squareup.retrofit2:adapter-rxjava3:2.9.0'
//android项目一般也会引入rxandroid
implementation 'io.reactivex.rxjava3:rxandroid:3.0.0'
@POST("user/login")
@FormUrlEncoded
Flowable<BaseResponse> login2(@Field("username") String userName, @Field("password")String pwd);

@GET("lg/collect/list/{pageNum}/json")
Flowable<ResponseBody> getArticle(@Path("pageNum") int pageNum);

使用适配器

Retrofit retrofit3 = new Retrofit.Builder()
    .baseUrl("https://www.wanandroid.com/")
    .callFactory(new OkHttpClient.Builder().cookieJar(new CookieJar(){
        @Override
        public void saveFromResponse(HttpUrl httpUrl, List<Cookie> list){
            cookies.put(httpUrl.host(), list);
        }
        
        @Override
        public List<Cookie> loadForRequest(HttpUrl httpUrl){
            List<Cookie> cookies = WanAndroidUnitTest.this.cookies.get(httpUrl.host());
            return cookies == null ? new ArrayList<>() : cookies;
        }
    }).build()) //添加Cookie
    .addConverterFactory(GsonConverterFactory.create())  //添加转换器
    .addCallAdapterFactory(RxJava3CallAdapterFactory.create())  //添加适配器
    .build();
WanAndroidService2 wanAndroidService3 = retrofit3.create(WanAndroidService2.class);

public void rxjavaTest(){
    wanAndroidService3.login2("lanceedu","123123")
        .flatMap(new Function<BaseResponse, Publisher<ResponseBody>>(){
            @Override
            public Publisher<ResponseBody> apply(BaseResponse baseResponse) throw Throwable{
               return wanAndroidService3.getArticle(0); 
            }
        }) //根据login2的结果,再去生成一个新的publish
        .observeOn(Scheduler.io()) //切换线程
        //.subscribeOn(Schedulers.newThread())  //Java环境切换主线程
        .subscribeOn(AndroidSchedulers.mainThread()) //观察的回调切换到Android主线程
        .subscribe(new Consumer<BaseResponse>(){
           @Override
            public void accept(ResponseBody responseBody) throw Throwable{
                System.out.println(responseBody.string());
            }
        });
    while(true){
        
    }
}

RxJava的转换器和适配器有很多(可以去github上查看),也可以自定义


五、Retrofit的转换器

在我们接到服务器的响应后,目前无论是OkHttp还是Retrofit都只能接收到String字符串类型的数据,在实际开发中,我们经常需要对字符串进行解析将其转变为一个Java Bean对象。比如服务器响应数据为JSON格式字符串,那么我们可以自己利用GSON库完成反序列化的操作。

而Retrofit提供了多个转换器使得响应能够完成自动的数据转换。以json解析为例:

添加依赖:

implementation 'com.squareup.retrofit2:converter-gson:2.9.0'

修改接口方法:

@POST("post")
@FormUrlEncoded
Call<JavaBean> post(@Field("username")String userName, @Field("password")String pwd);

使用wanandroid的API(wanandroid.com)进行实验

调用登录接口

1、常规写法:

针对登录接口,创建Java接口:

public class WanAndroidService{
    @POST("user/login")
    @FormUrlEncoding
    Call<ResponseBody> login(@Field(username)String username, @Field(password)String pwd);
}
public class WanAndroidUnitTest{
    
    Retrofit retrofit = new Retrofit.Builder().baseUrl("https://www.wanandroid.com").build();
    WanAndroidService wanAndroidService = retrofit.create(WanAndroidService.class);
    
    @Test
    public void loginTest(){
        Call<ResponseBody> call = wanAndroidService.login("lanceedu", "123123");
        Response<ResponseBody> response =  call.execute();
        String result = response.body().string();
        System.our.println(result);
    }
}

得到response后,希望将接收数据result转变为一个Java Bean,变为一个对象,那么必须自己去做 json 转换的事情。

json的使用,依赖gson库

implementation 'com.google.code.gson:gson:2.8.6'

然后,创建一个对应的 Java 类型

自己手动写较为繁琐,可以自动

搜索BEJSON,JSON工具 --> JSON生成Java实体类

将Json数据粘贴进去

在这里插入图片描述

点击下载文件,将代码目录复制到项目中

(试一下,先用类似postman的工具生成请求数据,然后转一下文件)

public class WanAndroidUnitTest{
    
    Retrofit retrofit = new Retrofit.Builder().baseUrl("https://www.wanandroid.com").build();
    WanAndroidService wanAndroidService = retrofit.create(WanAndroidService.class);
    
    @Test
    public void loginTest(){
        Call<ResponseBody> call = wanAndroidService.login("lanceedu", "123123");
        Response<ResponseBody> response =  call.execute();
        String result = response.body().string();
        System.our.println(result);
       
        //自己完成反序列化
        BaseResponse baseResponse = new Gson().fromJson(result, BaseResponse.class);
        System.out.println(baseResponse);
    }
}

2、使用Retrofit转换器

Retrofit转换器 :自动完成反序列化

//implementation 'com.google.code.gson:gson:2.8.6'
implementation 'com.squareup.retrofit2:convert-gson:2.9.0'
public class WanAndroidService{
    @POST("user/login")
    @FormUrlEncoding
    //Call<ResponseBody> login(@Field(username)String username, @Field(password)String pwd);
    //ResponseBody返回的是String,所以要改为我们自己的BaseResponse
     Call<BaseResponse> login(@Field(username)String username, @Field(password)String pwd);
}
public class WanAndroidUnitTest{
    
    Retrofit retrofit = new Retrofit.Builder().baseUrl("https://www.wanandroid.com").build();
    WanAndroidService wanAndroidService = retrofit.create(WanAndroidService.class);
    
    @Test
    public void loginTest(){
        Call<ResponseBody> call = wanAndroidService.login("lanceedu", "123123");
        Response<ResponseBody> response =  call.execute();
        String result = response.body().string();
        System.our.println(result);
    }
    
    //添加转换器
     Retrofit retrofit2 = new Retrofit.Builder().baseUrl("https://www.wanandroid.com").addConvertFactory(GsonConvert).build();
    WanAndroidService wanAndroidService2 = retrofit2.create(WanAndroidService.class);
    
    @Test
    public void loginConvertTest(){
       Call<ResponseBody> call = wanAndroidService2.login("lanceedu", "123123");
        Response<BaseResponse> response =  call.execute();
       // String result = response.body().string();
       // System.our.println(result);
        BaseResponse baseResponse = response.body();
        System.our.println(baseResponse);
    }
}

不加转换器的话,程序不知道该怎么将字符串转换为BaseResponse

其实,转换器内部就是自动帮我们完成的new Gson().fromJson(…) 操作



参考:

https://juejin.cn/post/6844903876559110151#heading-8

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android基础学习(十七)—— Retrofit 的相关文章

  • 适用于 IOS 和 Android 的支付网关 [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我正在开发一个应用程序 用户必须在澳大利亚餐馆通过应用程序 android ios 付款 有两种付款方式 通过 PayPal 或 Visa
  • 如何从该 JAVA 文件中提取 Delphi 类以与 Android 一起使用?

    我的Delphi XE7项目需要与FTDI FT311 Android 配件芯片 http www ftdichip com Products ICs FT311D html 他们帮助提供了一个 Android 演示 其中包括他们的 JAV
  • Gradle 构建错误:内存不足

    当我使用 gradle 构建时 它失败并显示以下信息 OpenJDK 64 Bit Server VM warning INFO os commit memory 0x0000000788800000 89128960 0 failed e
  • 如何在 ADB 连接期间禁用电池充电?

    问题描述 每次我在电脑和手机之间连接 USB 线时 电池都会自动充电 我想使用 ADB 协议 但我不想在 ADB 连接期间为电池充电 是否可以关闭此充电功能 当然 我该怎么做呢 环境 Android 操作系统 4 及更高版本的手机 我只需要
  • Android上如何模拟后台Activity因内存不足而被系统杀死的过程?

    我正在处理 内存不足 不再有后台进程 问题 当这种情况发生时 我的活动处于后台并被杀死 我正在尝试保存并加载实例状态来解决它 但因为它并不是每次都会发生 在这种情况下我应该如何测试我的活动 Thanks 您可以通过 adb 强制进程终止 g
  • 导入已经创建的sqlite数据库(xamarin)

    我正在使用 Xamarin 想知道如何导入我已经创建的 sqlite 数据库 到目前为止 我已将其添加到资产文件夹中 但不知道下一步从哪里开始 string localPath Path Combine System Environment
  • Android 中的 Sugar ORM:更新 SQLite 中保存的对象

    我是在 Android 上使用 SQLite 和 Sugar ORM 进行应用程序开发的新手 并尝试阅读 Sugar ORM 文档 但没有找到有关如何更新 SQLite 中保存的对象的任何信息 更改对象属性后还可以保存对象吗 就像是 Cus
  • Android:我可以创建一个不是矩形的视图/画布吗?圆形的?

    我有一个圆形视图 悬停在主要内容上方 gt 从屏幕出来的 z 轴方向 当有人点击屏幕时 我希望选择主要内容或悬停在上方的视图 当它覆盖主视图时 到目前为止效果很好 我在透明画布上有一个圆形物品 这意味着您可以看到该圆圈之外的背景的所有内容
  • 当不支持 Google Play 应用内结算 V.3 时

    在 Google Play 的应用内结算 V 3 中 有一个选项可以检查用户设备是否支持它 使用是否支持计费 http developer android com google play billing versions html meth
  • Android 版 jTwitter 授权错误

    我在我的 Android 应用程序中使用 jTwitter 库 直到前天一切都运转良好 但今天遇到异常 服务提供商响应错误 301 请帮助我 这是堆栈跟踪 02 21 21 07 27 258 E AndroidRuntime 4013 F
  • Emma 不生成coverage.ec

    我设置了艾玛 它曾经对我有用 然后我们更改了源代码 现在它没有生成coverage ec根本不 它确实生成coverage em 测试临近结束时 出现错误消息 exec INSTRUMENTATION CODE 0 echo Downloa
  • Android 纹理仅显示纯色

    我正在尝试在四边形上显示单个纹理 我有一个可用的 VertexObject 它可以很好地绘制一个正方形 或任何几何对象 现在我尝试扩展它来处理纹理 但纹理不起作用 我只看到一种纯色的四边形 坐标数据位于 arrayList 中 the ve
  • Jetpack 导航:如何从一个嵌套图的子级导航到另一个嵌套图的子级?

    导航结构 MainActivity nav root HomeFragment AuthNestedGraph nav auth BeforeOtpFragment home OtpFragment ProfileNestedGraph n
  • TextInputLayout 对于在 EditText 中以编程方式给出提示没有效果

    我有一个 EditText 它的父级是 TextInputLayout 我试图以编程方式为 EditText 提供提示 不在布局中 在这种情况下 文本输入提示动画不起作用 它像简单的 EditText 一样工作 有人可以建议如何处理它吗 下
  • 即使 Android M 上的移动数据已打开(有连接),也可以通过 WiFi(无连接)发送请求

    我必须在没有互联网连接的情况下将 UDP 数据包发送到 WiFi 模块 配有自己的 AP 但是当我将手机连接到 AP 时 Android 会在移动数据接口上重定向我的数据包 因为它有互联网连接 我使用下面的代码来完成我的工作 但它似乎不适用
  • 未解决的包含:“cocos2d.h” - Cocos2dx

    当我在 Eclipse 中导入 cocos2dx android 项目时 我的头文件上收到此警告 Unresolved inclusion cocos2d h 为什么是这样 它实际上困扰着我 该项目可以正确编译并运行 但我希望这种情况消失
  • 屏幕开/关检测

    在这里 我试图确定屏幕是否打开 但按下电源锁定 解锁按钮时它似乎不起作用 应用程序运行没有错误 但 if else 中的代码似乎没有效果 Edited现在代码可以工作了 谢谢Olgun 但媒体播放器播放不会停止 并且每次在屏幕上 离屏时都会
  • 在android中创建SQLite数据库

    我想在我的应用程序中创建一个 SQLite 数据库 其中包含三个表 我将向表中添加数据并稍后使用它们 但我喜欢保留数据库 就好像第一次安装应用程序时它会检查数据库是否存在 如果存在则更新它 否则如果不存在则创建一个新数据库 此外 我正在制作
  • 使用 DataBindingComponent 的 Inflate 方法

    当 Glide 成功渲染图像后 我在更新文本视图时看到此错误 致命异常 java lang IllegalStateException 必需 CustomBinding 类中的 DataBindingComponent 为 null 绑定适
  • 将焦距(以毫米为单位)转换为像素 - Android

    在 Android 中 我当前正在访问camera s焦距通过使用getFocalLength in Camera1 Camera2不是一个选择 我正在尝试完全填充当前的计算 focal length pix focal length m

随机推荐

  • C++之引用类型,深浅拷贝构造

    引用类型 给内存段取别名 int m 10 引用 给内存段取别名 所以需要给他一段内存段 而不只是声明 int n m 不是赋值的意思 是别名的意思 想要在被调函数中修改主调函数中定义的变量的值时 不需要将其地址传输给被调函数 直接传输变量
  • IDEA 使用技巧(快速生成xml文件)

    settiings 搜索File 找到 File and Code Templates 点击加号新建一个 Name 输入文件名 Extension 输入文件类型
  • PCL 生成空间直线点云

    目录 一 算法原理 二 代码实现 三 结果展示 一 算法原理 已知直线上一点和直线的方向向量 即可根据数学原理生成用于算法测试的标准直线点云 以下示例代码中 以直线上一点为中心点生成空间直线点云 其中点的个数为100个 相邻点之间的间隔为0
  • 微信小程序的的图片显示不出来

    图片的路径分两种 1 本地的图片如images文件夹下面的 images t1 jpg 或者是http localhost 8080 Teacher news t1 jpg 2 网络连接的图片http www baidu com vue n
  • python自动化操作, 三种方法解决滑动模块问题(后二种可跳过90%滑动,限制需要打开浏览器)

    selenium win32api pyautogui 元素定位 可无头进行访问 但是会被检测 基本用不了 sli ele driver find element By XPATH span id nc 1 n1z xpath 定位 if
  • 人工智能电话机器人一个顶10个,各版本系统搭建

    前接触多的就是电销行业 有电话机器人 VOS线路问题或要演示站AI技术支持 一个人面对多台电话不停地接听 特别是客户多时不知道应答哪一个 反而还把自己搞得心烦意乱 不过随着科技的发展 电销行业里出现了一个叫智能电销机器人的产品 自动应答客户
  • Innovus零基础lab学习全面复盘总

    Innovus零基础lab学习全面复盘总结 附完整版pdf 文章右侧广告为官方硬广告 与吾爱IC社区无关 用户勿点 点击进去后出现任何损失与社区无关 为了让各位训练营学员更快入门数字 IC 后端 从第八期 IC 训练营开始 小编以一个 数字
  • chatgpt 上方一直在转圈 白屏 空白

    下面空白 上面有个转圈 清除缓存 进入https platform openai com 返回刷新 更换节点 退出 Clash 软件 返回刷新 白屏 空白 来回换节点 就是换节点 有的时候是v p n的问题
  • MongoDB安装部署

    一 mongodb安装部署 关闭防火墙和selinux root mongodb iptables F root mongodb setenforce 0 root mongodb systemctl stop firewalld 2 指定
  • hdu 3879 最大密集子图(点和边均带权)(模板)

    最大权闭合图 可以用最大密集子图来解速度更快复杂度低 题解 胡伯涛 最小割模型在信息学竞赛中的应用 点和边均带权的最大密集子图 s i 权为U 点权绝对值和 边的所有权值 i t 权为U 点的值 点的度 u v 权值为w 意思是选了v后可以
  • Mybatis-plus使用手册

    Mybatis plus 1 定义 MyBatis Plus 是一个 Mybatis 增强版工具 在 MyBatis 上扩充了其他功能没有改变其基本功能 为了简化开发提交效率而存在 2 使用 SpringBoot 集成 MyBatis Pl
  • 相关性分析

    这里的相关性分析主要是线性相关性分析 当然其他的形状的相关性分析可以通过变换转换为线性相关性分析 但是 线性相关性分析始终是相关性分析的基础 线性相关分析的构建主要分为以下几种 直接绘制散点图 通过把点标出来主观上看是否是线性相关 绘制散点
  • 《动手学深度学习》第二十三天---稠密连接网络(DenseNet)

    一 DenseNet DenseNet作为另一种拥有较深层数的卷积神经网络 具有如下优点 1 相比ResNet拥有更少的参数数量 2 旁路加强了特征 feature 的重用 3 网络更易于训练 并具有一定的正则效果 4 缓解了gradien
  • Android Studio按钮背景色

    Android Studio按钮背景色改变 修改style xml theme xml 在Android Studio里写前端界面 修改Button的背景样式一直是系统默认的主题色就像这样 不管怎么改颜色都会是系统的默认主题色 这里我们需要
  • LC并联谐振电路的原理

    LC并联谐振电路的原理 2011 11 26 04 54 353744594 来自 手机知道 分类 电脑 网络 浏览6573次 LC并联谐振电路的原理 我怎么不能理解这个原理 能不能用生活中的例子来说明 谢谢 提问者采纳 2011 11 2
  • Springboot使用maven打包指定mainClass

    http jvm123 com 2019 12 springboot repackage html
  • 六、Linux系统编程:读写锁

    5 读写锁 读写锁 ReentrantReadWriteLock 就是读线程和读线程之间不互斥 读读不互斥 读写互斥 写写互斥 一个资源可以被多个读线程访问 也可以被一个写线程访问 但不能同时存在读写线程 读写互斥 读读共享 5 1 锁操作
  • Meetup预告

    2月份 我们匠心打磨的区块链跨链协作平台WeCross正式开源 技术白皮书同期发布 很多小伙伴认真品读研究之后 给我们提供了非常多及时和有益的反馈 我们深表感谢 关于WeCross的设计哲学 我们思考了四个方向 Synergetic 跨链业
  • Ceph入门到精通-存储集群ceph df 用量统计算法说明

    3 2 5 Ceph 如何计算数据使用量 used 值反映了使用的实际原始存储量 xxx GB xxx GB 代表可用的存储 其中较小的数字 和总存储容量 总容量反映了在复制 克隆或快照前存储数据的大小 因此 实际存储的数据量通常会超过名义
  • Android基础学习(十七)—— Retrofit

    Retrofit本身并没有提供网络访问的能力 但是它底层封装了OkHttp 也是由Square公司贡献的一个处理网络请求的开源项目 A type safe HTTP client for Android and Java https git