Android Retrofit API的用法

时间:2018-12-12 16:29:41

标签: java android retrofit

我仍然是Android改装API的初学者,我试图将变量传递到我的动态url中,但会在其中添加额外的字符,这些字符为“&=”。

这是我要消耗的端点的样子:

https://www.example.com/api/index.php?/Playlists/getTracks/00978d67f6933af10ec8bd8045f089a4/0673CC13-476A-4786-BF27-13ADD9C44261/9392

其中“ 9232”是我要传递的ID。但是,当我使用改造库时,这就是我生成的网址的样子:

https://www.example.com/api/index.php?/Playlists/getTracks/00978d67f6933af10ec8bd8045f089a4/0673CC13-476A-4786-BF27-13ADD9C44261/&=9392

请注意&= 已附加到发送即时消息

// Method that receives id and calls the retrofit API
private void getPlaylist(String id) {
    /*Create handle for the RetrofitInstance interface*/
    GetPlaylistRetrofitInterface playlistService = PlaylistClientInstance.getRetrofitInstance().create(GetPlaylistRetrofitInterface.class);

    Call<List<Playlists>> call = playlistService.getPlaylist(id);
    Log.d("URL", "getPlaylist: " + call.request().url());
    call.enqueue(new Callback<List<Playlists>>() {
        @Override
        public void onResponse(Call<List<Playlists>> call, Response<List<Playlists>> response) {
            myProgressBar.setVisibility(View.GONE);
            populatePlayList(response.body());
        }

        @Override
        public void onFailure(Call<List<Playlists>> call, Throwable throwable) {
            myProgressBar.setVisibility(View.GONE);
            Log.d("onFailure", "onFailure: " + throwable);
            Toast.makeText(getActivity(), throwable.getMessage(), Toast.LENGTH_LONG).show();
        }
    });
}

这是我要接收网址ID并将其附加到端点的界面

public interface GetPlaylistRetrofitInterface {
    @GET("index.php?/Playlists/getTracks/00978d67f6933af10ec8bd8045f089a4/0673CC13-476A-4786-BF27-13ADD9C44261/")
    Call<List<Playlists>> getPlaylist(@Query(value = "") String id);
}

我尝试在界面中使用@Path

public interface GetPlaylistRetrofitInterface {
    @GET("index.php?/Playlists/getTracks/00978d67f6933af10ec8bd8045f089a4/0673CC13-476A-4786-BF27-13ADD9C44261/{id}")
    Call<List<Playlists>> getPlaylist(@Path("id") String id);
}

但是,它使我的应用因以下错误而崩溃:

 java.lang.RuntimeException: Unable to start activity ComponentInfo{com.demoapp.HomeActivity}:
 java.lang.IllegalArgumentException: URL query string "/Playlists/getTracks/00978d67f6933af10ec8bd8045f089a4/0673CC13-476A-4786-BF27-13ADD9C44261/{id}" must not have replace block. For dynamic query parameters use @Query.
            for method GetPlaylistRetrofitInterface.getPlaylist
            at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2778)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2856)
            at android.app.ActivityThread.-wrap11(Unknown Source:0)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1589)
            at android.os.Handler.dispatchMessage(Handler.java:106)
            at android.os.Looper.loop(Looper.java:164)
            at android.app.ActivityThread.main(ActivityThread.java:6494)
            at java.lang.reflect.Method.invoke(Native Method)
            at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:440)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)

预先感谢

好的,所以我能够解决此问题,原来,我试图通过使用@Query传递查询到已经是查询的终结点,所以这就是我的解决方法:

这是我更新的GetPlaylistInterface

public interface GetPlaylistRetrofitInterface {
    @GET()
    Call<List<Playlists>> getPlaylist(@Url String url);
}

这是我更新的“获取播放列表”方法

private void getPlaylist(String id) {
    myProgressBar.setVisibility(View.VISIBLE);
    /*Create handle for the RetrofitInstance interface*/
    GetPlaylistRetrofitInterface playlistService = RetrofitClientInstance.getRetrofitInstance().create(GetPlaylistRetrofitInterface.class);
    Call<List<Playlists>> call = playlistService.getPlaylist(Config.playlist_url+id);
    Log.d("URL", "getPlaylist: " + call.request().url());
    call.enqueue(new Callback<List<Playlists>>() {
        @Override
        public void onResponse(Call<List<Playlists>> call, Response<List<Playlists>> response) {
            myProgressBar.setVisibility(View.GONE);
            populatePlayList(response.body());
        }

        @Override
        public void onFailure(Call<List<Playlists>> call, Throwable throwable) {
            myProgressBar.setVisibility(View.GONE);
            Log.d("onFailure", "onFailure: " + throwable);
            Toast.makeText(getActivity(), throwable.getMessage(), Toast.LENGTH_LONG).show();
        }
    });
}

这是包含端点的配置类:

public class Config {
    public static String playlist_url = "index.php?/Playlists/getTracks/00978d67f6933af10ec8bd8045f089a4/0673CC13-476A-4786-BF27-13ADD9C44261/";
    public static String playlist_details_url = "index.php?/Tracks/get/00978d67f6933af10ec8bd8045f089a4/0673CC13-476A-4786-BF27-13ADD9C44261/";
}

2 个答案:

答案 0 :(得分:0)

您正在使用@Query参数,默认情况下具有此语法。 您需要使用 @Path 而不是@Query。另外,您还需要在网址字符串中包含参数名称。

您的代码将看起来像这样:

public interface GetPlaylistRetrofitInterface {
@GET("index.php?/Playlists/getTracks/00978d67f6933af10ec8bd8045f089a4/0673CC13-476A-4786-BF27-13ADD9C44261/{id}")
Call<List<Playlists>> getPlaylist(@Path("id") String id);

}

答案 1 :(得分:0)

您几乎先拥有了它。您需要使用Query Parameter来查询String和Path以进行url / uri操作,似乎您已经将这些混淆了,下面的示例应该可以使用

public interface ApiServices {
@GET("index.php?/Playlists/getTracks/00978d67f6933af10ec8bd8045f089a4/0673CC13-476A-4786-BF27-13ADD9C44261/{id}")
Call<ResponseBody> getTracks(@Path("id") String id);
}

编辑:

您只需要定义接口并调用一次即可。上面是接口,下面是如何从类似您想要执行的功能中调用它……奇怪的是您拥有index.php?确定要这么做吗?

  // Method that receives id and calls the retrofit API
private void getPlaylist(String id) {
/*Create handle for the RetrofitInstance interface*/
OkHttpClient client = new OkHttpClient.Builder()


               .retryOnConnectionFailure(true)
               .build();
       Retrofit retrofit = new Retrofit.Builder()
               .client(client)
               .baseUrl("https://stepank.com/")
               .build();

       ApiServices service = retrofit.create(ApiServices.class);

       try {


           Call<ResponseBody> call = service.getTracks(id);
           call.enqueue(new Callback<ResponseBody>() {
               @Override
               public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
                   int result = -1;
                   setRefreshActionButtonState(false);

                   if (response.isSuccessful()) {
                       ///DO STUFF HERE WITH RESPONSE
                }
                                   }
               }

               @Override
               public void onFailure(Call<ResponseBody> call, Throwable t) {
                   t.printStackTrace();
               }
           });

}