Reputation: 35
I'm building an app that connects to a REST API and retrieves all the Employees in a Database. The app uses a RecyclerView to display all the Employees that are brought back in a CardView. The problem is nothing appears in the RecyclerView, and there is data that is being returned from the REST API.
It is an Android application, built in Java, using Pie for the OS. The project was created using the Basic Activity Template.
My Activity Class
public class ViewAllEmployees extends AppCompatActivity {
private List<Employee> employees;
private RecyclerView rcView;
private EmployeeAdapter adapter;
private Context context;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_view_all_employees);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
context = this;
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
FetchEmployeesTask async = new FetchEmployeesTask(new AsyncResponse() {
@Override
public void processFinished(List<Employee> output) {
Log.i("Async", "Finished");
}
});
async.execute();
rcView = findViewById(R.id.rcView);
adapter = new EmployeeAdapter(context, employees);
rcView.setAdapter(adapter);
rcView.setLayoutManager(new LinearLayoutManager(context));
}
private class FetchEmployeesTask extends AsyncTask<Void, Void, List<Employee>> {
public AsyncResponse delegate = null;
public FetchEmployeesTask(AsyncResponse asyncResponse){
delegate = asyncResponse;
}
@Override
protected List<Employee> doInBackground(Void... voids) {
return new APIHelper().fetchItems();
}
@Override
protected void onPostExecute(List<Employee> items) {
employees = items;
delegate.processFinished(items);
}
}
public interface AsyncResponse{
void processFinished(List<Employee> output);
}
}
The Employee Adapter for the RecyclerView
public class EmployeeAdapter extends RecyclerView.Adapter<EmployeeAdapter.EmployeeViewHolder> {
private List<Employee> employees;
private final LayoutInflater mInflater;
private Context context;
public int position;
public EmployeeAdapter(Context context, List<Employee> employeeList){
this.context = context;
employees = new ArrayList<>();
mInflater = LayoutInflater.from(context);
employees = employeeList;
}
@NonNull
@Override
public EmployeeViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
View mItemView = mInflater.inflate(R.layout.employee_card, viewGroup, false);
return new EmployeeViewHolder(mItemView, this);
}
@Override
public void onBindViewHolder(@NonNull EmployeeViewHolder employeeViewHolder, int i) {
Employee empl = employees.get(i);
employeeViewHolder.name.setText(empl.firstName + empl.lastName);
employeeViewHolder.department.setText(empl.department);
}
@Override
public int getItemCount() {
return employees == null ? 0 : employees.size();
}
class EmployeeViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public final TextView name;
public final TextView department;
private EmployeeAdapter adapter;
private final CardView card;
public EmployeeViewHolder(View itemView, EmployeeAdapter adapter) {
super(itemView);
name = itemView.findViewById(R.id.txtName);
department = itemView.findViewById(R.id.txtDepartment);
card = itemView.findViewById(R.id.cv);
itemView.setOnClickListener(this);
this.adapter = adapter;
}
@Override
public void onClick(View view) {
}
}
}
The APIHelper class
public class APIHelper {
private static final String ENDPOINT = "ENDPOINTADDRESS";
private static final String TAG = "APIHelper";
public byte[] getUrlBytes(String urlSpec) throws IOException{
URL url = new URL(urlSpec);
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
try{
ByteArrayOutputStream out = new ByteArrayOutputStream();
InputStream in = connection.getInputStream();
if(connection.getResponseCode() != HttpURLConnection.HTTP_OK){
return null;
}
int bytesRead = 0;
byte[] buffer = new byte[1024];
while((bytesRead = in.read(buffer)) > 0){
out.write(buffer, 0, bytesRead);
}
out.close();
return out.toByteArray();
}
finally {
connection.disconnect();
}
}
public String getUrlString(String urlSpec) throws IOException{
return new String((getUrlBytes(urlSpec)));
}
private void parseItems(List<Employee> employees, JSONArray jsonBody) throws IOException, JSONException {
JSONArray employeeArray = jsonBody;
for(int i = 0; i < employeeArray.length(); i++){
JSONObject jsonEmployee = employeeArray.getJSONObject(i);
JSONObject job = jsonEmployee.getJSONObject("Job");
Employee emp = new Employee();
//emp.setDepartment(jsonEmployee.getString("DepartmentId"));
emp.setEmail(jsonEmployee.getString("EmailAddress"));
emp.setEmployeeID(jsonEmployee.getString("EmployeeID"));
emp.setFirstName(jsonEmployee.getString("FirstName"));
emp.setLastName(jsonEmployee.getString("LastName"));
emp.setMiddleInitial(jsonEmployee.getString("MiddleInitial"));
emp.setPosition(job.getString("JobTitle"));
emp.setWorkNumber(jsonEmployee.getString("WorkNumber"));
employees.add(emp);
}
}
public List<Employee> fetchItems(){
List<Employee> employees = new ArrayList<>();
try{
String url = Uri.parse(ENDPOINT).buildUpon().build().toString();
String jsonString = getUrlString(url);
Log.i(TAG, "Received JSON: " + jsonString);
JSONArray jsonBody = new JSONArray(jsonString);
parseItems(employees, jsonBody);
}
catch (IOException ioe){
Log.e(TAG, "Failed to fetch items", ioe);
}
catch (JSONException je){
Log.e(TAG, "Failed to parse json:", je);
}
return employees;
}
The Layout for ViewAllEmployees
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:context=".ViewAllEmployees"
tools:showIn="@layout/activity_view_all_employees">
<android.support.v7.widget.RecyclerView
android:id="@+id/rcView"
android:layout_width="395dp"
android:layout_height="659dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
The Card View that is in the Recyclerview
<?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="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:padding="16dp">
<android.support.v7.widget.CardView
android:id="@+id/cv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
app:cardElevation="5dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/txtName"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="Name"/>
<TextView
android:id="@+id/txtDepartment"
android:layout_width="match_parent"
android:layout_height="127dp"
android:layout_below="@+id/txtName"
android:layout_alignEnd="@+id/txtName"
android:layout_marginTop="-142dp"
android:layout_marginEnd="0dp" />
</RelativeLayout>
</android.support.v7.widget.CardView>
</LinearLayout>
When the App is run, the RecyclerView should populate with CardViews that display an Employees name and their Department. However, it currently displays nothing.
Upvotes: 0
Views: 51
Reputation: 97
FetchEmployeesTask async = new FetchEmployeesTask(new AsyncResponse() {
@Override
public void processFinished(List<Employee> output) {
Log.i("Async", "Finished");
employees.addAll(items);
adapter.notifyDataSetChanged();
}
});
Upvotes: 0
Reputation: 921
You have to notify your adapter after populating your array list. Initialize your employee array list variable,then Do:
private class FetchEmployeesTask extends AsyncTask<Void, Void, List<Employee>> {
public AsyncResponse delegate = null;
public FetchEmployeesTask(AsyncResponse asyncResponse){
delegate = asyncResponse;
}
@Override
protected List<Employee> doInBackground(Void... voids) {
return new APIHelper().fetchItems();
}
@Override
protected void onPostExecute(List<Employee> items) {
employees.addAll(items);
adapter.notifyDataSetChanged();
delegate.processFinished(items);
}
}
Upvotes: 1