使用 Retrofit 2.0 从网络中提取信息 API

Using Retrofit 2.0 to extract information from a network API

我是 Java 编程的新手,在过去的几天里,我一直在试验一个基本的英语到希腊语语音翻译应用程序,纯粹是为了帮助我学习一些(更高级的)概念。这里有一个picture of the interface.

到目前为止,我已经获得了适用于两种语言的语音识别功能,并且我决定使用 MyMemory's API 作为 REST API 进行翻译。我正在使用 Retrofit 2.0.0-beta2 将 HTTP API 转换为 Java 接口。

目前我只是想从 MyMemory 中提取 word/phrase 的翻译并将其放在我的应用程序中的文本字段中。

目前,我的项目中有三个类:

  1. 翻译API(界面)
  2. 翻译数据
  3. 主要活动

翻译API

public interface TranslateAPI {
    @GET("get")
    void getTranslation(@Query("q") String request, Callback<TranslatedData> cb);
}

翻译数据

public class TranslatedData {
    String translatedText;

    public String getTranslatedText(){
        return translatedText;
    }
}

MainActivity(相关代码)

        public void translate(String toTranslate){
        String request = "=" + toTranslate + "&langpair=" + langPair;
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("http://api.mymemory.translated.net/")
                .build();
        TranslateAPI service = retrofit.create(TranslateAPI.class);
        service.getTranslation(request, new Callback<TranslatedData>() {
            @Override
            public void onResponse(Response<TranslatedData> response, Retrofit retrofit) {
                System.out.println("Success");
                //handle success
            }

            @Override
            public void onFailure(Throwable t) {
                System.out.println("Failure");
                //handle failure
            }
        });        
    }

这里出现了几个问题。首先,应用程序崩溃是因为 translate() 方法,我不明白为什么(我在 android 中的调试技能仍然不存在)。谁能帮我弄清楚为什么?

其次,我该如何解析来自服务器的响应?

我的代码是否有任何其他缺陷阻止应用 working/crashes 它?

如果我的问题不好或直截了当,我深表歉意,我对 Android 还是个新手,我发现大多数关于 Retrofit 的教程都含糊不清,因为一半的指南都是用 Retrofit 编写的1.x 和另一半 2.0.

在 Android Studio 的底部,您有 Android 监视器 ,您可以在其中找到包含错误的堆栈跟踪和更多信息,错误将在那里用红色突出显示。

要使用 Retrofit 2.0 解析来自服务器的响应,您需要指定一个转换器。示例:如果您想首先使用 Gson 作为您的实体转换器,您必须将该依赖项添加到您的 build.gradle 文件中。

compile 'com.squareup.retrofit:converter-gson:2.0.0-beta2'

然后你必须将它指定到你的 Retrofit 适配器中:

 Retrofit marvelApiAdapter = new Retrofit.Builder()
    .baseUrl(END_POINT)
    .addConverterFactory(GsonConverterFactory.create(new Gson()))
    .client(client)
    .build();

否则你会崩溃。也许最好的建议是你现在应该使用 Retrofit 1.9,它是稳定的,第二个版本在撰写本文时处于 beta 版本。另一方面,in this link 如果您正在学习 1.9 教程,您会找到一个关于如何从 1.9 版本迁移到 2.0 版本的很好的指南,这可能是:)

Retrofit 提供注解来构建正确的调用,顺便说一句,在这种特殊情况下你需要构建这种 URI:

http://api.mymemory.translated.net/get?q=hola&langpair=ES|EN

langpair 的参数值包括字符: | 需要转义(我花了一些时间),这可能是原因崩溃的原因。

您可以轻松修复它,将该参数设置为在 Retrofit 2 API 声明的签名中编码:

@GET("/get")
Call<TranslatedData> getTranslation(
    @Query("q") String textToTranslate, 
    @Query(value = "langpair", encoded = true) 
String languagePair);

然后对参数值进行编码:

mService.getTranslation(textToTranslate, URLEncoder.encode(fromLanguage + "|" + toLanguage))
    .enqueue(new Callback<TranslatedData>() {

您的响应实体也有一些错误,包含 translatedText 属性 的对象是一个名为 responseData 的 JsonObject,您需要设置正确的实体:

class TranslatedData {
    ResponseData responseData;
}

class ResponseData {
    String translatedText;
}

我 post 你 TranslateApi.java 的整个文件,我测试过它并且有效 ;)

package com.example.alex.finalproject;

import java.net.URLEncoder;
import retrofit.Call;
import retrofit.Callback;
import retrofit.GsonConverterFactory;
import retrofit.Response;
import retrofit.Retrofit;
import retrofit.http.GET;
import retrofit.http.Query;

class TranslatedData {
    ResponseData responseData;
}

class ResponseData {
    String translatedText;
}

public class TranslateAPI {
    private static final String ENDPOINT = "http://api.mymemory.translated.net";
    public final static String SPANISH = "ES";
    public final static String ENGLISH = "EN";


    private final TranslateService mService;

    public interface TranslateService {
        @GET("/get")
        Call<TranslatedData> getTranslation(
            @Query("q") String textToTranslate,
            @Query(value = "langpair", encoded = true)
        String languagePair);
    }

    public TranslateAPI() {
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(ENDPOINT)
                .addConverterFactory(GsonConverterFactory.create())
                .build();

        mService = retrofit.create(TranslateService.class);
    }

    public void translate(final String textToTranslate, final String fromLanguage, final String toLanguage) {
        mService.getTranslation(textToTranslate, URLEncoder.encode(fromLanguage + "|" + toLanguage))
            .enqueue(new Callback<TranslatedData>() {

                @Override
                public void onResponse(Response<TranslatedData> response, Retrofit retrofit) {
                    String output =
                        String.format("Translation of: %s, %s->%s = %s", textToTranslate,
                            fromLanguage, toLanguage, response.body().responseData.translatedText);

                    System.out.println("Result: " + output);
                }

                @Override public void onFailure(Throwable t) {
                    System.out.println("[DEBUG]" + " RestApi onFailure - " + "");
                }
            });
    }
}

你可以这样调用translate方法:

translateAPI.translate("hola", TranslateAPI.SPANISH, TranslateAPI.ENGLISH);

我的控制台结果:

I/System.out(31427): Result: Translation of: hola, ES->EN = hello