Retrofit 2では、次のようなサービスメソッドのアノテーションに完全なURLを設定できます。
public interface APIService {
@GET("http://api.mysite.com/user/list")
Call<Users> getUsers();
}
しかし、私のアプリでは、私のWebサービスのURLはコンパイル時にはわかりません。アプリはダウンロードしたファイルでそれらを取得するので、Retrofit 2をフルダイナミックURLで使用する方法については疑問に思います。
私はフルパスを設定しようとしました:
public interface APIService {
@GET("{fullUrl}")
Call<Users> getUsers(@Path("fullUrl") fullUrl);
}
new Retrofit.Builder()
.baseUrl("http://api.mysite.com/")
.build()
.create(APIService.class)
.getUsers("http://api.mysite.com/user/list"); // this url should be dynamic
.execute();
しかし、ここでは、Retrofitはそのパスが実際には完全なURLであることを認識しておらず、http://api.mysite.com/http%3A%2F%2Fapi.mysite.com%2Fuser%2Flist
をダウンロードしようとしています。
このような動的なURLでRetrofitを使用する方法についてのヒントはありますか。
ありがとうございました
私はあなたがそれを間違った方法で使っていると思います。これは changelog からの抜粋です。
New:@Urlパラメータアノテーションを使用すると、エンドポイントの完全なURLを渡すことができます。
だからあなたのインターフェースはこのようになるはずです:
public interface APIService {
@GET
Call<Users> getUsers(@Url String url);
}
私はURLの一部だけを置き換えたいと思いました、そしてこの解決策で、私はURL全体を渡す必要はなく、動的な部分だけを渡します。
public interface APIService {
@GET("users/{user_id}/playlists")
Call<List<Playlist> getUserPlaylists(@Path(value = "user_id", encoded = true) String userId);
}
@Path
アノテーションにencodedフラグを使うことができます。
public interface APIService {
@GET("{fullUrl}")
Call<Users> getUsers(@Path(value = "fullUrl", encoded = true) String fullUrl);
}
/
が%2F
に置き換えられるのを防ぎます。?
が%3F
に置き換えられてしまうのを防ぐことはできません。そのため、動的クエリ文字列を渡すことはできません。Retrofit 2.0.0-beta2以降、このURLからJSONに応答するサービスがある場合--- http:// myhost/mypath
以下は機能していません。
public interface ClientService {
@GET("")
Call<List<Client>> getClientList();
}
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://myhost/mypath")
.addConverterFactory(GsonConverterFactory.create())
.build();
ClientService service = retrofit.create(ClientService.class);
Response<List<Client>> response = service.getClientList().execute();
しかし、これは問題ありません。
public interface ClientService {
@GET
Call<List<Client>> getClientList(@Url String anEmptyString);
}
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://myhost/mypath")
.addConverterFactory(GsonConverterFactory.create())
.build();
ClientService service = retrofit.create(ClientService.class);
Response<List<Client>> response = service.getClientList("").execute();
これを使うことができます:
@GET("group/{id}/users")
Call<List<User>> groupList(@Path("id") int groupId, @Query("sort") String sort);
詳細についてはドキュメントを参照してください https://square.github.io/retrofit/
Step-1
Please define a method in Api interface like:-
@FormUrlEncoded
@POST()
Call<RootLoginModel> getForgotPassword(
@Url String apiname,
@Field(ParameterConstants.email_id) String username
);
Step-2ベストプラクティスとして、後付けインスタンスのクラスを定義します -
public class ApiRequest {
static Retrofit retrofit = null;
public static Retrofit getClient() {
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
logging.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient okHttpClient = new OkHttpClient().newBuilder()
.addInterceptor(logging)
.connectTimeout(60, TimeUnit.SECONDS)
.readTimeout(60, TimeUnit.SECONDS)
.writeTimeout(60, TimeUnit.SECONDS)
.build();
if (retrofit==null) {
retrofit = new Retrofit.Builder()
.baseUrl(URLConstants.base_url)
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}
} Step-あなたの活動の中で定義してください: -
final APIService request =ApiRequest.getClient().create(APIService.class);
Call<RootLoginModel> call = request.getForgotPassword("dynamic api
name",strEmailid);
コードが既に設定されていて、さまざまなインターフェースを変更したくない場合は、この link で説明されているソリューションを使用してください。主なポイントは、URLを更新し、Retrofitビルダーを再作成するメソッドchangeApiBaseUrl
です。
public class ServiceGenerator {
public static String apiBaseUrl = "http://futurestud.io/api";
private static Retrofit retrofit;
private static Retrofit.Builder builder =
new Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create())
.baseUrl(apiBaseUrl);
private static OkHttpClient.Builder httpClient =
new OkHttpClient.Builder();
// No need to instantiate this class.
private ServiceGenerator() {
}
public static void changeApiBaseUrl(String newApiBaseUrl) {
apiBaseUrl = newApiBaseUrl;
builder = new Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create())
.baseUrl(apiBaseUrl);
}
public static <S> S createService(Class<S> serviceClass, AccessToken token) {
String authToken = token.getTokenType().concat(token.getAccessToken());
return createService(serviceClass, authToken);
}
// more methods
// ...
}
次のように使用できます。
public class DynamicBaseUrlActivity extends AppCompatActivity {
public static final String TAG = "CallInstances";
private Callback<ResponseBody> downloadCallback;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_file_upload);
downloadCallback = new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
Log.d(TAG, "server contacted at: " + call.request().url());
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
Log.d(TAG, "call failed against the url: " + call.request().url());
}
};
// first request
FileDownloadService downloadService = ServiceGenerator.create(FileDownloadService.class);
Call<ResponseBody> originalCall = downloadService.downloadFileWithFixedUrl();
originalCall.enqueue(downloadCallback);
// change base url
ServiceGenerator.changeApiBaseUrl("http://development.futurestud.io/api");
// new request against new base url
FileDownloadService newDownloadService = ServiceGenerator.create(FileDownloadService.class);
Call<ResponseBody> newCall = newDownloadService.downloadFileWithFixedUrl();
newCall.enqueue(downloadCallback);
}
}
step -*1
movie_list_row.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:background="?android:attr/selectableItemBackground"
Android:clickable="true"
Android:focusable="true"
Android:orientation="horizontal"
Android:paddingLeft="@dimen/activity_horizontal_margin"
Android:paddingTop="@dimen/row_padding_vertical"
Android:paddingRight="@dimen/activity_horizontal_margin"
Android:paddingBottom="@dimen/row_padding_vertical">
<ImageView
Android:id="@+id/ivImage"
Android:layout_width="60dp"
Android:layout_height="60dp"
Android:layout_marginRight="10dp"
Android:src="@mipmap/ic_launcher" />
<LinearLayout
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:layout_weight="1"
Android:orientation="vertical">
<TextView
Android:id="@+id/title"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:layout_alignParentTop="true"
Android:text="Hello"
Android:textColor="@color/title"
Android:textSize="16dp"
Android:textStyle="bold" />
<TextView
Android:id="@+id/genre"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:layout_below="@id/title"
Android:text="realName" />
</LinearLayout>
<TextView
Android:id="@+id/year"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:layout_alignParentRight="true"
Android:text="Team"
Android:textColor="@color/year" />
</LinearLayout>
Api.Java
import org.json.JSONObject;
import Java.util.List;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.http.Field;
import retrofit2.http.FormUrlEncoded;
import retrofit2.http.GET;
import retrofit2.http.POST;
public interface Api {
String BASE_URL = "https://simplifiedcoding.net/demos/";
@GET("marvel")
Call<List<Hero>> getHeroes();
@FormUrlEncoded
@POST("/login")
public void login(@Field("username") String username, @Field("password") String password, Callback<List<Hero>> callback);
}
MoviesAdapter.Java import Android.content.Context;
import Android.support.v7.widget.RecyclerView;
import Android.view.LayoutInflater;
import Android.view.View;
import Android.view.ViewGroup;
import Android.widget.ImageView;
import Android.widget.TextView;
import Android.widget.Toast;
import com.squareup.picasso.Picasso;
import Java.util.List;
public class MoviesAdapter extends RecyclerView.Adapter<MoviesAdapter.MyViewHolder> {
private List<Hero> moviesList;
Context context;
public class MyViewHolder extends RecyclerView.ViewHolder {
public TextView title, year, genre;
public ImageView ivImage;
public MyViewHolder(View view) {
super(view);
title = (TextView) view.findViewById(R.id.title);
genre = (TextView) view.findViewById(R.id.genre);
year = (TextView) view.findViewById(R.id.year);
ivImage = view.findViewById(R.id.ivImage);
ivImage.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(context, "-" + moviesList.get(getAdapterPosition()).getName(), Toast.LENGTH_SHORT).show();
}
});
}
}
public MoviesAdapter(List<Hero> moviesList,Context context) {
this.moviesList = moviesList;
this.context = context;
}
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.movie_list_row, parent, false);
return new MyViewHolder(itemView);
}
@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
Hero movie = moviesList.get(position);
holder.title.setText(movie.getName());
holder.genre.setText(movie.getRealname());
holder.year.setText(movie.getTeam());
Picasso.get().load("http://i.imgur.com/DvpvklR.png").into(holder.ivImage);
}
@Override
public int getItemCount() {
return moviesList.size();
}
} main activity import Android.support.v7.app.AppCompatActivity;
import Android.os.Bundle;
import Android.support.v7.widget.DefaultItemAnimator;
import Android.support.v7.widget.LinearLayoutManager;
import Android.support.v7.widget.RecyclerView;
import Android.widget.ArrayAdapter;
import Android.widget.ListView;
import Android.widget.Toast;
import Java.util.ArrayList;
import Java.util.List;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
public class MainActivity extends AppCompatActivity {
private List<Hero> movieList = new ArrayList<>();
private RecyclerView recyclerView;
private MoviesAdapter mAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView=findViewById(R.id.recycler_view);
mAdapter = new MoviesAdapter(movieList,MainActivity.this);
RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getApplicationContext());
recyclerView.setLayoutManager(mLayoutManager);
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setAdapter(mAdapter);
//calling the method to display the heroes
getHeroes();
}
private void getHeroes() {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(ApiInterface.BASE_URL)
.addConverterFactory(GsonConverterFactory.create()) //Here we are using the GsonConverterFactory to directly convert json data to object
.build();
ApiInterface api = retrofit.create(ApiInterface.class);
Call<List<Hero>> call = api.getHeroes();
call.enqueue(new Callback<List<Hero>>() {
@Override
public void onResponse(Call<List<Hero>> call, Response<List<Hero>> response) {
List<Hero> heroList = response.body();
//Creating an String array for the ListView
String[] heroes = new String[heroList.size()];
//looping through all the heroes and inserting the names inside the string array
for (int i = 0; i < heroList.size(); i++) {
//heroes[i] = heroList.get(i).getName();
movieList.add(new Hero( heroList.get(i).getName(), heroList.get(i).getRealname(), heroList.get(i).getTeam()));
}
mAdapter.notifyDataSetChanged();
}
@Override
public void onFailure(Call<List<Hero>> call, Throwable t) {
Toast.makeText(getApplicationContext(), t.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
}
Hero.Java
package com.example.owner.apipractice;
public class Hero {
private String name;
private String realname;
private String team;
public Hero(String name, String realname, String team) {
this.name = name;
this.realname = realname;
this.team = team;
}
private String firstappearance;
private String createdby;
private String publisher;
private String imageurl;
private String bio;
public Hero(String name, String realname, String team, String firstappearance, String createdby, String publisher, String imageurl, String bio) {
this.name = name;
this.realname = realname;
this.team = team;
this.firstappearance = firstappearance;
this.createdby = createdby;
this.publisher = publisher;
this.imageurl = imageurl;
this.bio = bio;
}
public String getName() {
return name;
}
public String getRealname() {
return realname;
}
public String getTeam() {
return team;
}
public String getFirstappearance() {
return firstappearance;
}
public String getCreatedby() {
return createdby;
}
public String getPublisher() {
return publisher;
}
public String getImageurl() {
return imageurl;
}
public String getBio() {
return bio;
}
}