通过RetroFit 2调用Rest API并使用RecyclerView

时间:2018-06-02 07:54:29

标签: android json android-recyclerview retrofit

使用RetroFit调用Rest API时,我收到NullPointerException。 问题是我使用相同的方法和适配器结构与另一个具有相同json结构的调用,但由于某种原因只有这个调用得到NullPointerException,请尝试帮助:

例外日志:

java.lang.NullPointerException: Attempt to invoke virtual method 'java.util.List com.mad.footstats.data.goals.response.GoalsResponse.getTopGoalsList()' on a null object reference
    at com.mad.footstats.ui.fragments.StandingsFragment$2.onResponse(StandingsFragment.java:84)

这是片段,我通过改装调用Rest api:

public class StandingsFragment extends Fragment {
private final static String TAG = "Call Failed";
private StandingsAdapter mStandingsAdapter;
private RecyclerView mRecyclerView;
private ProgressBar mProgressBar;
private String mTournamentId;
private String mRegion;
private String mKey;
private GoalsAdapter mGoalsAdapter;
private AssistsAdapter mAssistsAdapter;

public StandingsFragment(){
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    final View view = inflater.inflate(R.layout.fragment_standings, container, false);
    // Getting the Arguments
    Bundle bundle = getArguments();
    mTournamentId = bundle.getString("tournament_id");
    mRegion = bundle.getString("region");
    mKey = bundle.getString("key");
    // Showing the Progressbar
    mProgressBar = view.findViewById(R.id.standings_progress_bar);
    // Creating an instance of the ApiInterface
    ApiInterface apiService = ApiClient.getClient().create(ApiInterface.class);
    // Calling to get the standings from the API
    Call<StandingsResponse> call = apiService.getStandings(mRegion,mTournamentId,mKey);
    // Logging the URL Call
    Log.wtf("URL Called", call.request().url() + "");
    call.enqueue(new Callback<StandingsResponse>() {
        @Override
        public void onResponse(Call<StandingsResponse> call, Response<StandingsResponse> response) {
            generateStandings(response.body().getStandings());
            mStandingsAdapter.notifyDataSetChanged();
            mProgressBar.setVisibility(View.GONE);
        }

        @Override
        public void onFailure(Call<StandingsResponse> call, Throwable t) {
            Log.e(TAG, t.toString());
            Toast.makeText(getActivity(), R.string.enqueue_failure, Toast.LENGTH_LONG).show();
            mProgressBar.setVisibility(View.GONE);
        }
    });
    // Calling to get the Goals from the API
    Call<GoalsResponse> goalsCall = apiService.getGoalsLeaders(mRegion,mTournamentId,mKey);
    // Logging the URL Call
    Log.wtf("URL Called", call.request().url() + "");
    goalsCall.enqueue(new Callback<GoalsResponse>() {
        @Override
        public void onResponse(Call<GoalsResponse> call, Response<GoalsResponse> response) {
            generateGoals(response.body().getTopGoalsList());
            mGoalsAdapter.notifyDataSetChanged();
        }
        @Override
        public void onFailure(Call<GoalsResponse> call, Throwable t) {

            Log.e(TAG, t.toString());
            Toast.makeText(getActivity(), R.string.enqueue_failure, Toast.LENGTH_LONG).show();
            mProgressBar.setVisibility(View.GONE);
        }
    });
    // Calling to get the Assists from the API
    Call<AssistsResponse> assistsCall = apiService.getAssistsLeaders(mRegion,mTournamentId,mKey);
    // Logging the URL Call
    Log.wtf("URL Called", call.request().url() + "");
    assistsCall.enqueue(new Callback<AssistsResponse>() {
        @Override
        public void onResponse(Call<AssistsResponse> call, Response<AssistsResponse> response) {
            generateAssists(response.body().getTopAssists());
            mGoalsAdapter.notifyDataSetChanged();
        }

        @Override
        public void onFailure(Call<AssistsResponse> call, Throwable t) {
            Log.e(TAG, t.toString());
            Toast.makeText(getActivity(), R.string.enqueue_failure, Toast.LENGTH_LONG).show();
        }
    });



    return view;
}

/**
 * Method to generate List of standings using RecyclerView with custom adapter
 */
private void generateStandings(final List<Standings> empDataList) {
    mRecyclerView = getView().findViewById(R.id.standings_rv);

    mStandingsAdapter = new StandingsAdapter(empDataList, R.layout.item_standings, getActivity());

    mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));

    mRecyclerView.setAdapter(mStandingsAdapter);
}

/**
 * Method to generate List of Goal leaders using RecyclerView with Custom adapter
 */
private void generateGoals(final List<TopGoals> topGoals){
    RecyclerView recyclerView = getView().findViewById(R.id.goals_rv);
    mGoalsAdapter = new GoalsAdapter(topGoals,R.layout.item_goals, getActivity());
    recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
    recyclerView.setAdapter(mGoalsAdapter);
}

/**
 * Method to generate List of assists leaders using RecyclerView with Custom adapter
 */
private void generateAssists(final List<TopAssists> topAssists){
    RecyclerView assistsRecyclerView = getView().findViewById(R.id.assists_rv);
    mAssistsAdapter = new AssistsAdapter(topAssists,R.layout.item_assists, getActivity());
    assistsRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
    assistsRecyclerView.setAdapter(mAssistsAdapter);
}

此外,以下是从API调用生成的Json示例:

{
"tournament": {
    "id": "sr:tournament:136",
    "name": "A-League",
    "sport": {
        "id": "sr:sport:1",
        "name": "Soccer"
    },
    "category": {
        "id": "sr:category:34",
        "name": "Australia",
        "country_code": "AUS"
    },
    "current_season": {
        "id": "sr:season:45280",
        "name": "A-League 17\/18",
        "start_date": "2017-10-06",
        "end_date": "2018-05-28",
        "year": "17\/18"
    }
},
"season_coverage_info": {
    "season_id": "sr:season:45280",
    "scheduled": 148,
    "played": 143,
    "max_coverage_level": "gold",
    "max_covered": 140,
    "min_coverage_level": "bronze"
},
"top_assists": [{
    "assists": 12,
    "rank": 1,
    "player": {
        "id": "sr:player:22132",
        "name": "George, Leroy"
    },
    "team": {
        "id": "sr:competitor:5970",
        "name": "Melbourne Victory",
        "abbreviation": "MEL"
    }
    }, {
    "assists": 10,
    "rank": 2,
    "player": {
        "id": "sr:player:139782",
        "name": "Petratos, Dimitri"
    },
    "team": {
        "id": "sr:competitor:2934",
        "name": "Newcastle United Jets FC",
        "abbreviation": "NEW"
    }
}]

如果您需要更多代码,请立即提供。

编辑:这是GoalsResponse.Java:

public class GoalsResponse {

@SerializedName("generated_at")
@Expose
private String mGeneratedAt;

@SerializedName("schema")
@Expose
private String mSchema;

@SerializedName("top_goals")
private List<TopGoals> mTopGoalsList;

public String getGeneratedAt() {
    return mGeneratedAt;
}

public void setGeneratedAt(String generatedAt) {
    mGeneratedAt = generatedAt;
}

public String getSchema() {
    return mSchema;
}

public void setSchema(String schema) {
    mSchema = schema;
}

public List<TopGoals> getTopGoalsList() {
    return mTopGoalsList;
}

public void setTopGoalsList(List<TopGoals> topGoalsList) {
    mTopGoalsList = topGoalsList;
}

Json回复中的TopAssists和TopGoals示例:

{
"tournament": {
    "id": "sr:tournament:136",
    "name": "A-League",
    "sport": {
        "id": "sr:sport:1",
        "name": "Soccer"
    },
    "category": {
        "id": "sr:category:34",
        "name": "Australia",
        "country_code": "AUS"
    },
    "current_season": {
        "id": "sr:season:45280",
        "name": "A-League 17\/18",
        "start_date": "2017-10-06",
        "end_date": "2018-05-28",
        "year": "17\/18"
    }
},
"season_coverage_info": {
    "season_id": "sr:season:45280",
    "scheduled": 148,
    "played": 143,
    "max_coverage_level": "gold",
    "max_covered": 140,
    "min_coverage_level": "bronze"
},
"top_goals": [{
    "goals": 32,
    "rank": 1,
    "player": {
        "id": "sr:player:159665",
        "name": "Salah, Mohamed"
    },
    "team": {
        "id": "sr:competitor:44",
        "name": "Liverpool FC",
        "abbreviation": "LIV"
    }
}, {
    "goals": 30,
    "rank": 2,
    "player": {
        "id": "sr:player:108579",
        "name": "Kane, Harry"
    },
    "team": {
        "id": "sr:competitor:33",
        "name": "Tottenham Hotspur",
        "abbreviation": "TOT"
    }
}],
"top_assists": [{
    "assists": 12,
    "rank": 1,
    "player": {
        "id": "sr:player:22132",
        "name": "George, Leroy"
    },
    "team": {
        "id": "sr:competitor:5970",
        "name": "Melbourne Victory",
        "abbreviation": "MEL"
    }
    }, {
    "assists": 10,
    "rank": 2,
    "player": {
        "id": "sr:player:139782",
        "name": "Petratos, Dimitri"
    },
    "team": {
        "id": "sr:competitor:2934",
        "name": "Newcastle United Jets FC",
        "abbreviation": "NEW"
    }
}]

1 个答案:

答案 0 :(得分:1)

你应该做的是,在Retrofit中首先检查响应是否成功,所以将onResponse回调更改为:

goalsCall.enqueue(new Callback<GoalsResponse>() {
    @Override
    public void onResponse(Call<GoalsResponse> call, Response<GoalsResponse> response) {
        if(response.isSuccessful()){
            Log.d(TAG, response.body().toString())
            generateGoals(response.body().getTopGoalsList());
            mmGoalsAdapter.notifyDataSetChanged();
        }
        else{
            Log.d(TAG,"in not successfull" + response.code().toString())
        }
    }
    @Override
    public void onFailure(Call<GoalsResponse> call, Throwable t) {

        Log.e(TAG, t.toString());
        Toast.makeText(getActivity(), R.string.enqueue_failure, Toast.LENGTH_LONG).show();
        mProgressBar.setVisibility(View.GONE);
    }
});

如果Android方面的一切正常,那么你应该可以在isSuccessful()块中看到Log语句。否则,服务器可能出现问题。

如果有帮助,请告诉我。