当尝试填充recyclerview时,Gson的改造2+显示错误

时间:2017-08-19 23:17:36

标签: android json gson retrofit2

我正在使用改装2+和gson库来从rest api获取数据。但每当我尝试运行我的应用程序时,它都会显示以下错误:

  

“预计BEGIN_ARRAY,但在第1行第1行路径为STRING”。

因此我尝试了很多来识别问题。这是我的json序列化器的代码。 Json就是这样给出的。在某些情况下,某些字段缺失,例如title未包含在所有情况中。

Api数据:

 [
    {
    "_id": "fhfh49879787989",
    "dn": "CN=9879798789",
    "whenChanged": "20170704065349.0Z",
    "name": "Student",
    "mail": "student@mail.com",
    "updated_at": "2017-07-04T18:22:43.624Z"
  },
  {
    "_id": "595bdcf32c67a3f9ee6c2a25",
    "dn": "CN=dsfdsfsdfsf",
    "givenName": "Accounting Office",
    "whenChanged": "20170801114732.0Z",
    "name": "Accounting",
    "mail": "accounting@mail.com",
    "updated_at": "2017-07-04T18:22:43.641Z"
  },
  {
    "_id": "584ab3b4122d13e1b0d1578d",
    "dn": "CN=sfdfsfsdfl",
    "sn": "Abels",
    "title": "Student",
    "givenName": "Gardrut",
    "whenChanged": "20170807150844.0Z",
    "department": "PMO",
    "company": "Multi Lmited",
    "name": "Mike Lizz",
    "mail": "mail@yahoo.com",
    "mobile": "+1321646498",
    "updated_at": "2016-12-09T13:37:56.175Z"
  },
  {
    "_id": "584ab3b3122d13e1b0d15735",
    "dn": "CN=xdfsdfsfsdf",
    "sn": "Acsdff",
    "title": "Software Engineer",
    "givenName": "Olin",
    "whenChanged": "20170810064841.0Z",
    "department": "Head",
    "company": "Private limited",
    "name": "James Oliver",
    "mail": "mail@gmail.com",
    "mobile": "+41228",
    "updated_at": "2016-12-09T13:37:55.813Z"
  },
  ....
 ]

POJO:

public class ColleagueModel implements Serializable {

    @Expose
    private String _id;
    @Expose
    private String dn;
    @Expose
    private String givenName;
    @Expose
    private String whenChanged;
    @Expose
    private String name;
    @Expose
    private String mail;
    @Expose
    private String updatedAt;
    @Expose
    private String sn;
    @Expose
    private String title;
    @Expose
    private String department;
    @Expose
    private String company;
    @Expose
    private String mobile; 

    // getter and setter...

我的服务类:

public interface ColleagueApiService {
    @GET("/api/users")
    Call<List<ColleagueModel>> getAllColleagues();
}

休息maneger类:

public class ColleagueRestManager {

    public ColleagueApiService mColleagueService;

    public ColleagueApiService getColleagueService() {

        if (mColleagueService == null) {
            Gson gson = new GsonBuilder()
                .setLenient()
                .serializeNulls()
                .create();

            Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(Constants.HTTP.BASE_URL)
                .addConverterFactory(GsonConverterFactory.create(gson))
                .build();

            mColleagueService = retrofit.create(ColleagueApiService.class);
        }
        return mColleagueService;
    }
}

适配器类:

public class MyColleaguesAdapter extends RecyclerView.Adapter<MyColleaguesAdapter.ColleagueHolder> {

    public static String TAG = MyColleaguesAdapter.class.getSimpleName();

    private List<ColleagueModel> mColleague;

    public MyColleaguesAdapter() {
        mColleague = new ArrayList<>();
    }

    private List<MyColleagueModel> myColleagueModels;     

    public interface ColleagueListListener {    
    }

    public void addColleague(ColleagueModel colleague) {
        Log.d(TAG,colleague.getName());
        mColleague.add(colleague);
        notifyDataSetChanged();
    }

    // create new views (invoked by the layout manager)
    @Override
    public ColleagueHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        //inflate a new colleague view
        View view = LayoutInflater
            .from(parent.getContext())
            .inflate(R.layout.colleage_row_layout,parent,false);
        return new ColleagueHolder(view);
    }

    @Override
    public void onBindViewHolder(ColleagueHolder holder, int position) {

        ColleagueModel currentColleague = mColleague.get(position);

        holder.colleagueName.setText(currentColleague.getName());
        holder.companyName.setText(currentColleague.getCompany());
        holder.jobTitle.setText(currentColleague.getTitle());
    }

    @Override
    public int getItemCount() {
        return mColleague.size();
    }

    public class ColleagueHolder extends RecyclerView.ViewHolder{
        public CardView cardView;
        public ImageView colleaguePicture;
        public TextView colleagueName;
        public TextView companyName;
        public TextView jobTitle;

    public ColleagueHolder(View itemView) {
        super(itemView);
        colleaguePicture = itemView.findViewById(R.id.colleague_picture);
        colleagueName = itemView.findViewById(R.id.colleague_name);
        companyName = itemView.findViewById(R.id.company_name);
        jobTitle = itemView.findViewById(R.id.job_title);
        cardView = itemView.findViewById(R.id.cardview_user);
    }
}

最后是活动类:

public class MyColleaguesPage extends AppCompatActivity  {

    private RecyclerView recyclerView;
    private MyColleaguesAdapter adapter;  
    private Controller mController;
    private ColleagueRestManager mManager;

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

        // Showing and Enabling clicks on the Home/Up button
        if (getSupportActionBar() != null) {
            getSupportActionBar().setDisplayHomeAsUpEnabled(true);
            getSupportActionBar().setDisplayShowHomeEnabled(true);
        }
        configViews();

        mManager = new ColleagueRestManager();
        Call<List<ColleagueModel>> colleagueList = mManager.getColleagueService().getAllColleagues();
        colleagueList.enqueue(new Callback<List<ColleagueModel>>() {
            @Override
            public void onResponse(Call<List<ColleagueModel>> call, Response<List<ColleagueModel>> response) {

                if(response.isSuccessful()) {
                    List<ColleagueModel> colleagueList = response.body();

                    for (int i = 0; i < colleagueList.size(); i++) {
                        ColleagueModel colleague = colleagueList.get(i);
                        adapter.addColleague(colleague);
                    }
                } else {
                    int sc = response.code();
                    switch (sc){
                        case 400:
                            Log.e("Error 400", "Bad Request");
                            break;
                        case 404:
                            Log.e("Error 404", "Not Found");
                            break;
                        default:
                            Log.e("Error", "Generic Error");
                    }
                }
            }

            @Override
            public void onFailure(Call<List<ColleagueModel>> call, Throwable t) {
                Toast.makeText(getApplicationContext(), t.getMessage(), Toast.LENGTH_LONG).show();
                Log.d("Error Message:"+"",t.getMessage());
            }
        })    
    }

    private void configViews() {
        recyclerView = this.findViewById(R.id.colleagues_recycler);
        recyclerView.setHasFixedSize(true);
        recyclerView.setLayoutManager(new LinearLayoutManager(MyColleaguesPage.this));
        recyclerView.setRecycledViewPool(new RecyclerView.RecycledViewPool());

        adapter = new MyColleaguesAdapter();
        recyclerView.setAdapter(adapter);
    }
}

获取api的重要级别:

public class Constants {
    public static final class HTTP {
        public static final String BASE_URL = "https://app.com"; //not given the real url
    }

    public static final class DATABASE {
    }
}

已编辑的正文

    08-20 07:51:02.334 3421-5002/demo.app.com.bluapp_client_and D/OkHttp: --> GET https://app.blu-pa.com/api/users http/1.1
08-20 07:51:02.334 3421-5002/demo.app.com.bluapp_client_and D/OkHttp: --> END GET
08-20 07:51:02.377 1346-1367/? W/audio_hw_generic: Not supplying enough data to HAL, expected position 860742 , only wrote 707760
08-20 07:51:02.383 1346-1366/? W/audio_hw_generic: Not supplying enough data to HAL, expected position 707956 , only wrote 707760
08-20 07:51:02.386 3421-3426/demo.app.com.bluapp_client_and I/art: Do partial code cache collection, code=59KB, data=59KB
08-20 07:51:02.387 3421-3426/demo.app.com.bluapp_client_and I/art: After code cache collection, code=50KB, data=54KB
08-20 07:51:02.387 3421-3426/demo.app.com.bluapp_client_and I/art: Increasing code cache capacity to 256KB
08-20 07:51:02.392 3421-3440/demo.app.com.bluapp_client_and D/EGL_emulation: eglMakeCurrent: 0xa494e540: ver 2 0 (tinfo 0xa494d430)
08-20 07:51:02.404 1581-1601/? I/ActivityManager: Displayed demo.app.com.bluapp_client_and/.activity.myColleague.MyColleaguesPage: +83ms

    08-20 07:51:02.657 3421-5002/demo.app.com.bluapp_client_and D/OkHttp: <-- 200  https://app.blu-pa.com/login?callback=%2F (322ms)
08-20 07:51:02.657 3421-5002/demo.app.com.bluapp_client_and D/OkHttp: x-dns-prefetch-control: off
08-20 07:51:02.657 3421-5002/demo.app.com.bluapp_client_and D/OkHttp: x-frame-options: SAMEORIGIN
08-20 07:51:02.657 3421-5002/demo.app.com.bluapp_client_and D/OkHttp: strict-transport-security: max-age=15552000; includeSubDomains
08-20 07:51:02.658 3421-5002/demo.app.com.bluapp_client_and D/OkHttp: x-download-options: noopen
08-20 07:51:02.658 3421-5002/demo.app.com.bluapp_client_and D/OkHttp: x-content-type-options: nosniff
08-20 07:51:02.658 3421-5002/demo.app.com.bluapp_client_and D/OkHttp: x-xss-protection: 1; mode=block
08-20 07:51:02.658 3421-5002/demo.app.com.bluapp_client_and D/OkHttp: set-cookie: language=de-DE; Max-Age=86400; Path=/; Expires=Mon, 21 Aug 2017 07:51:05 GMT
08-20 07:51:02.658 3421-5002/demo.app.com.bluapp_client_and D/OkHttp: set-cookie: connect.sid=s%3Ah-1Pju1IRtwJwNG5VU5Ja0t1OPujcaHz.Bd6gMWB8Q3DtgOpP%2BHnMuh6QY5VGHwcChbOqTRVVee0; Path=/; HttpOnly
08-20 07:51:02.658 3421-5002/demo.app.com.bluapp_client_and D/OkHttp: content-type: text/html; charset=utf-8
08-20 07:51:02.658 3421-5002/demo.app.com.bluapp_client_and D/OkHttp: etag: W/"8af-hp6ns0Ui95kDbe9rVovQHfKz5pA"
08-20 07:51:02.658 3421-5002/demo.app.com.bluapp_client_and D/OkHttp: vary: Accept-Encoding

1 个答案:

答案 0 :(得分:0)

正如我在您的改造日志中所看到的,没有您期望的答案。您根据服务器实现发出请求whitout发送令牌或etag。通常,在编辑某些个人信息时会使用etag。

有一个重定向到登录页面:https://app.blu-pa.com/login?callback=%2F (322ms)

Retrofit正在检索登录页面(D/OkHttp: content-type: text/html; charset=utf-8)的html(Retrofit返回html作为正文中的字符串),这就是为什么你得到"Expected BEGIN_ARRAY but was STRING at line 1 column 1 path $".

添加标题,您在users请求中从登录中获得的令牌已准备就绪。

修改

您应该使用拦截器将令牌添加到每个请求

OkHttpClient.Builder httpClient = new OkHttpClient.Builder();  
httpClient.addInterceptor(new Interceptor() {  
    @Override
    public Response intercept(Interceptor.Chain chain) throws IOException {
        Request original = chain.request();

        Request request = original.newBuilder()
            .header("Authorization", "YourTokenHere")
            .method(original.method(), original.body())
            .build();

        return chain.proceed(request);
    }
}

OkHttpClient client = httpClient.build(); 
Retrofit retrofit = new Retrofit.Builder().client(client).build();

现在,您可以自行决定如何存储和检索令牌。

您可以阅读更多关于incerceptor的here