ชุดติดตั้งเพิ่มเติม 2 - URL แบบไดนามิก


181

ด้วย Retrofit 2 คุณสามารถตั้งค่า URL แบบเต็มในหมายเหตุประกอบของวิธีการบริการเช่น:

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

อย่างไรก็ตามในแอพของฉัน 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

คำใบ้ใด ๆ ที่ฉันสามารถใช้ Retrofit กับ URL แบบไดนามิกเช่นนั้นได้?

ขอบคุณ


5
สำหรับผู้ค้นหาในอนาคตจะมีคำแนะนำเกี่ยวกับ URL แบบไดนามิกพร้อมชุดติดตั้งเพิ่มเติม: futurestud.io/tutorials/ …
peitek

คำตอบ:


389

ฉันคิดว่าคุณกำลังใช้มันในทางที่ผิด นี่คือข้อความที่ตัดตอนมาจากการเปลี่ยนแปลง :

ใหม่: คำอธิบายประกอบพารามิเตอร์ @Url อนุญาตให้ส่งผ่าน URL ที่สมบูรณ์สำหรับจุดสิ้นสุด

ดังนั้นอินเทอร์เฟซของคุณควรเป็นเช่นนี้:

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

1
@ pdegand59 มันใหม่เอี่ยม :) ดูchangelog
Yazazzello

2
ทำไมต้องมี baseurl ถึงแม้ว่า url สำหรับจุดปลายนั้นจะเป็น fullurl
Billyjoker

13
ถ้าฉันใช้คำอธิบายประกอบ @Url นี้ แล้วเราควรเขียนอะไรใน. baseUrl () ??
Gulnaz Ghanchi

12
คุณควรเขียน URL หลักของคุณ พารามิเตอร์ @Url จะแทนที่อยู่ดี
Yazazzello

5
ฉันพยายามเพิ่ม URL เช่นเดียวกับข้างบน แต่ baseUrl ที่ฉันตั้งค่าตามปกติสำหรับตัวติดตั้งเพิ่มเติมจะแทนที่ URL แบบเต็มที่ฉันระบุในพารามิเตอร์ดังนั้นแทนที่จะเป็นdynamic.comจะได้รับการแปลเป็นMyBaseUrl / http: //dynamic.com
Jonathan

129

ฉันต้องการแทนที่เพียงส่วนหนึ่งของ url และด้วยวิธีนี้ฉันไม่ต้องผ่าน url ทั้งหมดเพียงส่วนไดนามิก:

public interface APIService {

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

ช่วยฉันได้มาก ... ขอบคุณ
Siddhesh Shirodkar

33

คุณสามารถใช้การตั้งค่าสถานะที่เข้ารหัสใน@Pathคำอธิบายประกอบ:

public interface APIService {
  @GET("{fullUrl}")
  Call<Users> getUsers(@Path(value = "fullUrl", encoded = true) String fullUrl);
}
  • ซึ่งจะช่วยป้องกันการเปลี่ยนด้วย/%2F
  • อย่างไรก็ตามมันจะไม่บันทึกคุณจาก?การถูกแทนที่ด้วย%3Fดังนั้นคุณยังคงไม่สามารถส่งผ่านสตริงการสืบค้นแบบไดนามิกได้

มันไม่ใช่การพิมพ์ผิด
Matthew Bahr

และจะทำอย่างไรเพื่อแทนที่% 3F ด้วย?
Yogesh

19

ในฐานะของ Retrofit 2.0.0-beta2 หากคุณมีบริการที่ตอบสนอง JSON จาก URL นี้: 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();


3

ขั้นตอนที่ 1

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

ขั้นตอนที่ 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-3 กำหนดในกิจกรรมของคุณ: -

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

2

ห้องสมุดRetrofitHelper ที่เขียนด้วย kotlin จะช่วยให้คุณทำการโทรด้วย API โดยใช้โค้ดสองสามบรรทัดและคุณสามารถใช้URL, ส่วนหัวและ Params ที่แตกต่างกันในการโทรทุกครั้ง

เพิ่ม URL หลายรายการในคลาสแอปพลิเคชันของคุณเช่นนี้:

class Application : Application() {

    override fun onCreate() {
    super.onCreate()

        retrofitClient = RetrofitClient.instance
                    //api url
                .setBaseUrl("https://reqres.in/")
                    //you can set multiple urls
        //                .setUrl("example","http://ngrok.io/api/")
                    //set timeouts
                .setConnectionTimeout(4)
                .setReadingTimeout(15)
                    //enable cache
                .enableCaching(this)
                    //add Headers
                .addHeader("Content-Type", "application/json")
                .addHeader("client", "android")
                .addHeader("language", Locale.getDefault().language)
                .addHeader("os", android.os.Build.VERSION.RELEASE)
            }

        companion object {
        lateinit var retrofitClient: RetrofitClient

        }
    }  

จากนั้นใช้ URL ที่คุณต้องการในการโทรของคุณ:

retrofitClient.Get<GetResponseModel>()
            //set base url
            .setBaseUrlKey("example")
            //set path
            .setPath("api/users/2")
            //set url params Key-Value or HashMap
            .setUrlParams("KEY","Value")
            .setResponseHandler(GetResponseModel::class.java,
                object : ResponseHandler<GetResponseModel>() {
                    override fun onSuccess(response: Response<GetResponseModel>) {
                        super.onSuccess(response)
                        //handle response
                    }
                }).run(this)

สำหรับข้อมูลเพิ่มเติมโปรดดูเอกสารประกอบ


2

URL แบบไดนามิกพร้อมวิธีการรับและโพสต์ใน Retrofit (MVVM)

ชุดติดตั้งเพิ่มบริการ:

public interface NetworkAPIServices {

@POST()
Observable<JsonElement> executXYZServiceAPI(@Url String url,@Body AuthTokenRequestModel param);


@GET
Observable<JsonElement> executeInserInfo(@Url String url);

ระดับบริการ MVVM:

   public Observable<JsonElement> executXYZServiceAPI(ModelObject object) {
    return networkAPIServices.authenticateAPI("url",
            object);
}

 public Observable<JsonElement> executeInserInfo(String ID) {
    return networkAPIServices.getBank(DynamicAPIPath.mergeUrlPath("url"+ID)));
}

และติดตั้งคลาสไคลเอนต์ใหม่

 @Provides
@Singleton
@Inject
@Named("provideRetrofit2")
Retrofit provideRetrofit(@Named("provideRetrofit2") Gson gson, @Named("provideRetrofit2") OkHttpClient okHttpClient) {


   builder = new Retrofit.Builder();
    if (BaseApplication.getInstance().getApplicationMode() == ApplicationMode.DEVELOPMENT) {
        builder.baseUrl(NetworkURLs.BASE_URL_UAT);
    } else {
        builder.baseUrl(NetworkURLs.BASE_URL_PRODUCTION);
    }


    builder.addCallAdapterFactory(RxJava2CallAdapterFactory.create());
    builder.client(okHttpClient);
    builder.addConverterFactory(GsonConverterFactory.create(gson));


    return builder.build();
}

เช่นนี่คือ URL: https://gethelp.wildapricot.com/th/articles/549-changing-your

baseURL: https://gethelp.wildapricot.com

คงเหลือ @Url: / en / บทความ / 549-change-your (ซึ่งคุณผ่านในคลาสบริการย้อนยุค)


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

0

หากคุณมีการตั้งค่ารหัสของคุณอยู่แล้วและคุณไม่ต้องการเปลี่ยนแปลงอินเทอร์เฟซต่าง ๆ ที่คุณสามารถทำได้ให้ใช้วิธีแก้ปัญหาที่อธิบายไว้ในลิงค์นี้ จุดหลักคือวิธีchangeApiBaseUrlที่อัปเดต URL และสร้างตัวติดตั้งเพิ่มใหม่อีกครั้ง

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);
    }
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.