variable library android retrofit

android - library - Retrofit 2-URL dinámica



retrofit2 java (8)

Con Retrofit 2, puede establecer una URL completa en la anotación de un método de servicio como:

public interface APIService { @GET("http://api.mysite.com/user/list") Call<Users> getUsers(); }

Sin embargo, en mi aplicación, la URL de mis servicios web no se conoce en el momento de la compilación, la aplicación los recupera en un archivo descargado, así que me pregunto cómo puedo usar Retrofit 2 con una URL dinámica completa.

Traté de establecer un camino completo como:

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();

Pero aquí, Retrofit no ve que la ruta es en realidad una URL completa y está tratando de descargar http://api.mysite.com/http%3A%2F%2Fapi.mysite.com%2Fuser%2Flist

¿Alguna pista de cómo podría usar Retrofit con una URL tan dinámica?

Gracias


A partir de Retrofit 2.0.0-beta2, si tiene un servicio que responde JSON desde esta URL: http://myhost/mypath

Lo siguiente no funciona:

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();

Pero esto está bien:

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();


Creo que lo estás usando de manera incorrecta. Aquí hay un extracto del changelog :

Nuevo: la anotación de parámetros @Url permite pasar una URL completa para un punto final.

Entonces su interfaz debería ser así:

public interface APIService { @GET Call<Users> getUsers(@Url String url); }


Puede usar el indicador codificado en la anotación @Path :

public interface APIService { @GET("{fullUrl}") Call<Users> getUsers(@Path(value = "fullUrl", encoded = true) String fullUrl); }

  • Esto evitará el reemplazo de / con %2F .
  • ¿No te salvará de ? sin embargo, se reemplaza por %3F , por lo que aún no puede pasar cadenas de consulta dinámicas.

Puedes usar esto:

@GET("group/{id}/users")

Call<List<User>> groupList(@Path("id") int groupId, @Query("sort") String sort);

Para obtener más información, consulte la documentación https://square.github.io/retrofit/


Quería reemplazar solo una parte de la url, y con esta solución, no tengo que pasar toda la url, solo la parte dinámica:

public interface APIService { @GET("users/{user_id}/playlists") Call<List<Playlist> getUserPlaylists(@Path(value = "user_id", encoded = true) String userId); }


Si ya tiene su configuración de código y no desea realizar cambios en las diferentes interfaces que puede, use la solución descrita en este link . El punto principal es el método changeApiBaseUrl que actualiza la URL y recrea el constructor Retrofit.

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 // ... }

Puede usarlo de la siguiente manera:

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); } }


Paso 1

Please define a method in Api interface like:- @FormUrlEncoded @POST() Call<RootLoginModel> getForgotPassword( @Url String apiname, @Field(ParameterConstants.email_id) String username );

Paso-2 Para una mejor práctica, defina una clase para la instancia de actualización: -

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; }

} Paso-3 define en tu actividad: -

final APIService request =ApiRequest.getClient().create(APIService.class); Call<RootLoginModel> call = request.getForgotPassword("dynamic api name",strEmailid);


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; } }