使用 Retrofit 发送带有参数的 Post 请求

Posted

技术标签:

【中文标题】使用 Retrofit 发送带有参数的 Post 请求【英文标题】:Send Post Request with params using Retrofit 【发布时间】:2015-07-22 17:48:09 【问题描述】:

我尝试使用 Retrofit 库在 android 上使用 API 未成功,但在使用 POSTMAN 时,我可以看到预期的结果。

邮递员设置

api url (base+controller)

HTTP 方法设置为 POST

点击了 from-data 或 x-www-form-urlencoded

然后我在键/值字段上传递两个参数。

安卓改造设置

@POST("/GetDetailWithMonthWithCode")
void getLandingPageReport(@Query("code") String code,
                          @Query("monthact") String monthact,
                          Callback<LandingPageReport> cb);

@FormUrlEncoded
@POST("/GetDetailWithMonthWithCode")
void getLandingPageReport(@Field("code") String code,
                          @Field("monthact") String monthact,
                          Callback<LandingPageReport> cb);

这些选项都不起作用。但结果是 。

更新

使用标准HttpClient(和HttpPost)类的相同设置可以正常工作。

HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost(url);

List<NameValuePair> urlParameters = new ArrayList<NameValuePair>();
urlParameters.add(new BasicNameValuePair("code", "testcode"));
urlParameters.add(new BasicNameValuePair("monthact", "feb-2015"));

post.setEntity(new UrlEncodedFormEntity(urlParameters));

HttpResponse response = client.execute(post);

为什么我不能执行这个请求并在 Retrofit 中得到正确的响应?

更新 2

@POST("/GetDetailWithMonthWithCode")
void getLandingPageReport(@Query("code") String code,
                          @Query("monthact") String monthact,
                          Callback<List<LandingPageReport>> cb);

@FormUrlEncoded
@POST("/GetDetailWithMonthWithCode")
void getLandingPageReport(@Field("code") String code,
                          @Field("monthact") String monthact,
                          Callback<List<LandingPageReport>>> cb);

玩了一圈之后,我想我找到了问题的根源。我已更新我的改造代码以接收List&lt;LandingPageReport&gt;。但是现在出现这个错误

retrofit.RetrofitError: com.google.gson.JsonSyntaxException: java.lang.IllegalStateException:应为 BEGIN_ARRAY,但为 BEGIN_OBJECT 在第 1 行第 2 列路径 $

原因是我消耗了 2 个 api(webapi 和 wcf)。我所有的其他json 响应都是对象数组。 [,] 但在这次通话中我收到了这个


  "GetDetailWithMonthWithCodeResult": [
     
        "code": "test",
        "field1": "test",
     
   ]

但我仍然无法解析响应。

【问题讨论】:

GetDetailWithMonth&amp;Code这部分可能无效 你的意思是什么?我该怎么做?在 ios 上工作,我所做的就是将此字符串“par1=adads&par2=asd”转换为 NSDATA 并将其放入请求中。 symbol &amp; 就像请求参数的分隔符,所以你应该将你的 API 方法(在你的 API 中)重命名为 GetDetailWithMonthAndCode 我已经更新了帖子。先生,当我在这里写帖子时,这只是一个错误。 错误可能出在您的 API 中。另外,您应该使用GET http 方法来获取数据,而不是POST 【参考方案1】:

我找到了解决方案。这个问题是我的班级结构中的一个问题。所以我像下面的示例一样更新了它们。

public class LandingPageReport 

    private ArrayList<LandingPageReportItem> GetDetailWithMonthWithCodeResult;

    // + Getter Setter methods


public class LandingPageReportItem 

    private String code;

    private String field1;

    // + Getter Setter methods

然后我使用这个改造配置

@POST("/GetDetailWithMonthWithCode")
void getLandingPageReport(@Field("code") String code,
                          @Field("monthact") String monthact,
                          Callback<LandingPageReport> cb);

【讨论】:

【参考方案2】:

这是一个简单的解决方案,我们不需要使用 JSON

public interface RegisterAPI 
@FormUrlEncoded
@POST("/RetrofitExample/insert.php")
public void insertUser(
        @Field("name") String name,
        @Field("username") String username,
        @Field("password") String password,
        @Field("email") String email,
        Callback<Response> callback);

发送数据的方法

private void insertUser()
    //Here we will handle the http request to insert user to mysql db
    //Creating a RestAdapter
    RestAdapter adapter = new RestAdapter.Builder()
            .setEndpoint(ROOT_URL) //Setting the Root URL
            .build(); //Finally building the adapter

    //Creating object for our interface
    RegisterAPI api = adapter.create(RegisterAPI.class);

    //Defining the method insertuser of our interface
    api.insertUser(

            //Passing the values by getting it from editTexts
            editTextName.getText().toString(),
            editTextUsername.getText().toString(),
            editTextPassword.getText().toString(),
            editTextEmail.getText().toString(),

            //Creating an anonymous callback
            new Callback<Response>() 
                @Override
                public void success(Response result, Response response) 
                    //On success we will read the server's output using bufferedreader
                    //Creating a bufferedreader object
                    BufferedReader reader = null;

                    //An string to store output from the server
                    String output = "";

                    try 
                        //Initializing buffered reader
                        reader = new BufferedReader(new InputStreamReader(result.getBody().in()));

                        //Reading the output in the string
                        output = reader.readLine();
                     catch (IOException e) 
                        e.printStackTrace();
                    

                    //Displaying the output as a toast
                    Toast.makeText(MainActivity.this, output, Toast.LENGTH_LONG).show();
                

                @Override
                public void failure(RetrofitError error) 
                    //If any error occured displaying the error as toast
                    Toast.makeText(MainActivity.this, error.toString(),Toast.LENGTH_LONG).show();
                
            
    );

现在我们可以使用 php aur 任何其他服务器端脚本来获取发布请求。

来源Android Retrofit Tutorial

【讨论】:

只是从源评论中复制,cz 我遇到了问题,RestAdapter doesnt get resolved please help me out..【参考方案3】:

我认为最好的方法是将其发送到POST Body,这意味着您将创建一个新的 POJO,但有些人可能最喜欢这个实现。

public interface APIInterface 
    @POST("/GetDetailWithMonthWithCode")
    List<LandingPageReport> getLandingPageReport(@Body Report report);

然后使用构造函数、getter 和 setter 来制作你的 POJO。

public static class Report 
    private String code;
    private String monthact;

    public Report(String code, String monthact) 
        this.code = code;
        this.monthact = monthact;  
    

    // Getters and Setters...

就用正常的方式来称呼它。

Call<List<Report>> request = apiInterface
    .createRetrofitAPIInterface()
    .getLandingPageReport(new Report(code, monthact));

【讨论】:

【参考方案4】:

build.gradle

      compile 'com.google.code.gson:gson:2.6.2'

      compile 'com.squareup.retrofit2:retrofit:2.1.0'// compulsory

      compile 'com.squareup.retrofit2:converter-gson:2.1.0' //for retrofit conversion

登录API放两个参数

    
        "UserId": "1234",
        "Password":"1234"
    

登录响应

    
        "UserId": "1234",
        "FirstName": "Keshav",
        "LastName": "Gera",
        "ProfilePicture": "312.113.221.1/GEOMVCAPI/Files/1.500534651736E12p.jpg"
    

APIClient.java

    import retrofit2.Retrofit;
    import retrofit2.converter.gson.GsonConverterFactory;

    class APIClient 

        public static final String BASE_URL = "Your Base Url ";
        private static Retrofit retrofit = null;

        public static Retrofit getClient() 
            if (retrofit == null) 
                retrofit = new Retrofit.Builder()
                        .baseUrl(BASE_URL)
                        .addConverterFactory(GsonConverterFactory.create())
                        .build();
            
            return retrofit;
        
    

APIInterface接口

    interface APIInterface 

        @POST("LoginController/Login")
        Call<LoginResponse> createUser(@Body LoginResponse login);
    

登录Pojo

    package pojos;

    import com.google.gson.annotations.SerializedName;

    public class LoginResponse 


        @SerializedName("UserId")
        public String UserId;
        @SerializedName("FirstName")
        public String FirstName;
        @SerializedName("LastName")
        public String LastName;
        @SerializedName("ProfilePicture")
        public String ProfilePicture;
        @SerializedName("Password")
        public String Password;
        @SerializedName("ResponseCode")
        public String ResponseCode;
        @SerializedName("ResponseMessage")
        public String ResponseMessage;

        public LoginResponse(String UserId, String Password) 
            this.UserId = UserId;
            this.Password = Password;
        

        public String getUserId() 
            return UserId;
        

        public String getFirstName() 
            return FirstName;
        

        public String getLastName() 
            return LastName;
        

        public String getProfilePicture() 
            return ProfilePicture;
        

        public String getResponseCode() 
            return ResponseCode;
        

        public String getResponseMessage() 
            return ResponseMessage;
        
    

MainActivity

    package com.keshav.retrofitloginexampleworkingkeshav;

    import android.app.Dialog;
    import android.os.Bundle;
    import android.support.v7.app.AppCompatActivity;
    import android.util.Log;
    import android.view.View;
    import android.widget.Button;
    import android.widget.EditText;
    import android.widget.TextView;
    import android.widget.Toast;

    import pojos.LoginResponse;
    import retrofit2.Call;
    import retrofit2.Callback;
    import retrofit2.Response;
    import utilites.CommonMethod;

    public class MainActivity extends AppCompatActivity 

        TextView responseText;
        APIInterface apiInterface;

        Button loginSub;
        EditText et_Email;
        EditText et_Pass;
        private Dialog mDialog;
        String userId;
        String password;

        @Override
        protected void onCreate(Bundle savedInstanceState) 
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);

            apiInterface = APIClient.getClient().create(APIInterface.class);

            loginSub = (Button) findViewById(R.id.loginSub);
            et_Email = (EditText) findViewById(R.id.edtEmail);
            et_Pass = (EditText) findViewById(R.id.edtPass);

            loginSub.setOnClickListener(new View.OnClickListener() 
                @Override
                public void onClick(View v) 
                    if (checkValidation()) 
                        if (CommonMethod.isNetworkAvailable(MainActivity.this))
                            loginRetrofit2Api(userId, password);
                        else
                            CommonMethod.showAlert("Internet Connectivity Failure", MainActivity.this);
                    
                
            );
        

        private void loginRetrofit2Api(String userId, String password) 
            final LoginResponse login = new LoginResponse(userId, password);
            Call<LoginResponse> call1 = apiInterface.createUser(login);
            call1.enqueue(new Callback<LoginResponse>() 
                @Override
                public void onResponse(Call<LoginResponse> call, Response<LoginResponse> response) 
                    LoginResponse loginResponse = response.body();

                    Log.e("keshav", "loginResponse 1 --> " + loginResponse);
                    if (loginResponse != null) 
                        Log.e("keshav", "getUserId          -->  " + loginResponse.getUserId());
                        Log.e("keshav", "getFirstName       -->  " + loginResponse.getFirstName());
                        Log.e("keshav", "getLastName        -->  " + loginResponse.getLastName());
                        Log.e("keshav", "getProfilePicture  -->  " + loginResponse.getProfilePicture());

                        String responseCode = loginResponse.getResponseCode();
                        Log.e("keshav", "getResponseCode  -->  " + loginResponse.getResponseCode());
                        Log.e("keshav", "getResponseMessage  -->  " + loginResponse.getResponseMessage());
                        if (responseCode != null && responseCode.equals("404")) 
                            Toast.makeText(MainActivity.this, "Invalid Login Details \n Please try again", Toast.LENGTH_SHORT).show();
                         else 
                            Toast.makeText(MainActivity.this, "Welcome " + loginResponse.getFirstName(), Toast.LENGTH_SHORT).show();
                        
                    
                

                @Override
                public void onFailure(Call<LoginResponse> call, Throwable t) 
                    Toast.makeText(getApplicationContext(), "onFailure called ", Toast.LENGTH_SHORT).show();
                    call.cancel();
                
            );
        

        public boolean checkValidation() 
            userId = et_Email.getText().toString();
            password = et_Pass.getText().toString();

            Log.e("Keshav", "userId is -> " + userId);
            Log.e("Keshav", "password is -> " + password);

            if (et_Email.getText().toString().trim().equals("")) 
                CommonMethod.showAlert("UserId Cannot be left blank", MainActivity.this);
                return false;
             else if (et_Pass.getText().toString().trim().equals("")) 
                CommonMethod.showAlert("password Cannot be left blank", MainActivity.this);
                return false;
            
            return true;
        
    

CommonMethod.java

    public class CommonMethod 


        public static final String DISPLAY_MESSAGE_ACTION =
                "com.codecube.broking.gcm";

        public static final String EXTRA_MESSAGE = "message";

        public  static boolean isNetworkAvailable(Context ctx) 
            ConnectivityManager connectivityManager
                    = (ConnectivityManager)ctx.getSystemService(Context.CONNECTIVITY_SERVICE);
            NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
            return activeNetworkInfo != null && activeNetworkInfo.isConnected();
        

        public static void showAlert(String message, Activity context) 

            final AlertDialog.Builder builder = new AlertDialog.Builder(context);
            builder.setMessage(message).setCancelable(false)
                    .setPositiveButton("OK", new DialogInterface.OnClickListener() 
                        public void onClick(DialogInterface dialog, int id) 

                        
                    );
            try 
                builder.show();
             catch (Exception e) 
                e.printStackTrace();
            

        
    

activity_main.xml

    <LinearLayout android:layout_
        android:layout_
        android:focusable="true"
        android:focusableInTouchMode="true"
        android:orientation="vertical"
        xmlns:android="http://schemas.android.com/apk/res/android">

            <ImageView
                android:id="@+id/imgLogin"
                android:layout_
                android:layout_
                android:layout_gravity="center"
                android:layout_marginTop="20dp"
                android:padding="5dp"
                android:background="@mipmap/ic_launcher_round"
                />

            <TextView
                android:id="@+id/txtLogo"
                android:layout_
                android:layout_
                android:layout_below="@+id/imgLogin"
                android:layout_centerHorizontal="true"
                android:text="Holostik Track and Trace"
                android:textSize="20dp"
                android:visibility="gone" />

            <android.support.design.widget.TextInputLayout
                android:id="@+id/textInputLayout1"
                android:layout_
                android:layout_
                android:layout_marginLeft="@dimen/box_layout_margin_left"
                android:layout_marginRight="@dimen/box_layout_margin_right"
                android:layout_marginTop="8dp"
                android:padding="@dimen/text_input_padding">

                <EditText
                    android:id="@+id/edtEmail"
                    android:layout_
                    android:layout_
                    android:layout_marginTop="5dp"
                    android:ems="10"
                    android:fontFamily="sans-serif"
                    android:gravity="top"
                    android:hint="Login ID"
                    android:maxLines="10"
                    android:paddingLeft="@dimen/edit_input_padding"
                    android:paddingRight="@dimen/edit_input_padding"
                    android:paddingTop="@dimen/edit_input_padding"
                    android:singleLine="true"></EditText>

            </android.support.design.widget.TextInputLayout>

            <android.support.design.widget.TextInputLayout
                android:id="@+id/textInputLayout2"
                android:layout_
                android:layout_
                android:layout_below="@+id/textInputLayout1"
                android:layout_marginLeft="@dimen/box_layout_margin_left"
                android:layout_marginRight="@dimen/box_layout_margin_right"
                android:padding="@dimen/text_input_padding">

                <EditText
                    android:id="@+id/edtPass"
                    android:layout_
                    android:layout_
                    android:focusable="true"
                    android:fontFamily="sans-serif"
                    android:hint="Password"
                    android:inputType="textPassword"

                    android:singleLine="true" />

            </android.support.design.widget.TextInputLayout>

            <RelativeLayout
                android:id="@+id/rel12"
                android:layout_
                android:layout_
                android:layout_below="@+id/textInputLayout2"
                android:layout_marginTop="10dp"
                android:layout_marginLeft="10dp"
                >

                <Button
                    android:id="@+id/loginSub"
                    android:layout_
                    android:layout_
                    android:layout_alignParentRight="true"
                    android:layout_centerVertical="true"
                    android:background="@drawable/border_button"
                    android:paddingLeft="30dp"
                    android:paddingRight="30dp"
                    android:layout_marginRight="10dp"
                    android:text="Login"
                    android:textColor="#ffffff" />    
            </RelativeLayout>

    </LinearLayout>

【讨论】:

谁对布局中的dimen感到困惑..***.com/questions/28005048/… 连接性的一些更新..***.com/questions/32547006/… 在 ApiInterface.java 中定义了方法“createUser”的位置?【参考方案5】:

你应该为它创建一个界面,让它运行良好

public interface Service 
    @FormUrlEncoded
    @POST("v1/EmergencyRequirement.php/?op=addPatient")
    Call<Result> addPerson(@Field("BloodGroup") String bloodgroup,
           @Field("Address") String Address,
           @Field("City") String city, @Field("ContactNumber") String  contactnumber, 
           @Field("PatientName") String name, 
           @Field("Time") String Time, @Field("DonatedBy") String donar);

或者您可以访问http://teachmeandroidhub.blogspot.com/2018/08/post-data-using-retrofit-in-android.html

你可以访问https://github.com/rajkumu12/GetandPostUsingRatrofit

【讨论】:

非常感谢您的分享。这对我有用【参考方案6】:

Post data to backend using retrofit

 implementation 'com.squareup.retrofit2:retrofit:2.8.1'
 implementation 'com.squareup.retrofit2:converter-gson:2.8.1'
 implementation 'com.google.code.gson:gson:2.8.6'
 implementation 'com.squareup.okhttp3:logging-interceptor:4.5.0'

public interface UserService 
  @POST("users/")
  Call<UserResponse> userRegistration(@Body UserRegistration 
    userRegistration);




public class ApiClient 

    private static Retrofit getRetrofit()
        HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor();
        httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);

        OkHttpClient okHttpClient = new OkHttpClient
                .Builder()
                .addInterceptor(httpLoggingInterceptor)
                .build();

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("http://api.larntech.net/")
                .addConverterFactory(GsonConverterFactory.create())
                .client(okHttpClient)
                .build();



        return retrofit;

    


    public static UserService getService()
        UserService userService = getRetrofit().create(UserService.class);
        return userService;
    


【讨论】:

以上是关于使用 Retrofit 发送带有参数的 Post 请求的主要内容,如果未能解决你的问题,请参考以下文章

改造:如何发送带有常量字段的 POST 请求?

使用Retrofit发送POST请求提交JSON数据

使用 Retrofit with Field 传递参数

使用 Retrofit 发送 POST 请求并接收 Json 响应无法使用响应数据我需要将其传递给另一个活动

如何在 Android 中使用 Retrofit 发送 JSON POST 请求,并接收字符串响应

如何发送带有 URL 参数和 JSON 正文的 POST? [关闭]