0
votes

NullPointerException and No adapter attached; skipping layout occurs everytime I test this app on the gennymotion.i have read other questions related to same problem but none help.

logcat

09-20 13:21:13.738 4658-4658/com.example.kiran.detailapp E/AndroidRuntime: FATAL EXCEPTION: main Process: com.example.kiran.detailapp, PID: 4658 java.lang.NullPointerException: Attempt to invoke interface method 'int java.util.List.size()' on a null object reference at com.example.kiran.detailapp.RecyclerAdapter.getItemCount(RecyclerAdapter.java:38) at android.support.v7.widget.RecyclerView.dispatchLayoutStep1(RecyclerView.java:3493) at android.support.v7.widget.RecyclerView.onMeasure(RecyclerView.java:3019) at android.view.View.measure(View.java:17430) at android.widget.RelativeLayout.measureChild(RelativeLayout.java:697) at android.widget.RelativeLayout.onMeasure(RelativeLayout.java:481) at android.view.View.measure(View.java:17430) at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5463) at android.widget.FrameLayout.onMeasure(FrameLayout.java:430) at android.support.v7.widget.ContentFrameLayout.onMeasure(ContentFrameLayout.java:139) at android.view.View.measure(View.java:17430) at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5463) at android.support.v7.widget.ActionBarOverlayLayout.onMeasure(ActionBarOverlayLayout.java:393) at android.view.View.measure(View.java:17430) at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5463) at android.widget.FrameLayout.onMeasure(FrameLayout.java:430) at android.view.View.measure(View.java:17430) at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5463) at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1436) at android.widget.LinearLayout.measureVertical(LinearLayout.java:722) at android.widget.LinearLayout.onMeasure(LinearLayout.java:613) at android.view.View.measure(View.java:17430) at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5463) at android.widget.FrameLayout.onMeasure(FrameLayout.java:430) at com.android.internal.policy.impl.PhoneWindow$DecorView.onMeasure(PhoneWindow.java:2560) at android.view.View.measure(View.java:17430) at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:2001) at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1166) at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1372) at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1054) at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5779) at android.view.Choreographer$CallbackRecord.run(Choreographer.java:767) at android.view.Choreographer.doCallbacks(Choreographer.java:580) at android.view.Choreographer.doFrame(Choreographer.java:550) at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:753) at android.os.Handler.handleCallback(Handler.java:739) at android.os.Handler.dispatchMessage(Handler.java:95) at android.os.Looper.loop(Looper.java:135) at android.app.ActivityThread.main(ActivityThread.java:5221) at java.lang.reflect.Method.invoke(Native Method) at java.lang.reflect.Method.invoke(Method.java:372) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)

Contact.java

package com.example.kiran.detailapp;
import com.google.gson.annotations.SerializedName;
public class Contact {
    @SerializedName("name")
    private String Name;

    @SerializedName("email")
    private String Email;

    public String getName() {
        return Name;
    }

    public void setName(String name) {
        Name = name;
    }

    public String getEmail() {
        return Email;
    }

    public void setEmail(String email) {
        Email = email;
    }
}

ApiClient.java

    package com.example.kiran.detailapp;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;

public class ApiClient {

    public static final String BASE_URL = "http://10.0.3.2/ContactApp/";

    public static Retrofit retrofit = null;

    public static Retrofit getApiClient()
    {
        retrofit = new Retrofit.Builder().baseUrl(BASE_URL)
                .addConverterFactory(GsonConverterFactory.create()).build();
        return retrofit;
    }
}

ApiInterface.java

    package com.example.kiran.detailapp;

import java.util.List;

import retrofit2.Call;
import retrofit2.http.POST;
public interface ApiInterface {


    @POST("ReadContacts.php")
    Call<List<Contact>> getContacts();
}

RecyclerAdapter.java

    package com.example.kiran.detailapp;

import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import org.w3c.dom.Text;

import java.util.List;

public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.MyViewHolder> {

    private List<Contact> contacts;
    public RecyclerAdapter(List<Contact> contacts)
    {
        this.contacts = contacts;
    }

    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.row_item,parent,false);
        return new MyViewHolder(view);
    }

    @Override
    public void onBindViewHolder(MyViewHolder holder, int position) {
        holder.Name.setText(contacts.get(position).getName());
        holder.Email.setText(contacts.get(position).getEmail());
    }

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

    public class MyViewHolder extends RecyclerView.ViewHolder {
        TextView Name,Email;
        public MyViewHolder(View itemView) {
            super(itemView);
            Name = (TextView) itemView.findViewById(R.id.name);
            Email = (TextView) itemView.findViewById(R.id.email);

        }
    }
}

MainActivity.java

    package com.example.kiran.detailapp;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;

import java.util.List;

import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

public class MainActivity extends AppCompatActivity {

    private RecyclerView recyclerView;
    private RecyclerView.LayoutManager layoutManager;
    private RecyclerAdapter adapter;
    private List<Contact> contacts;
    private ApiInterface apiInterface;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        adapter = new RecyclerAdapter(contacts);
        recyclerView = (RecyclerView) findViewById(R.id.Recycleview);
        layoutManager = new LinearLayoutManager(this);
        recyclerView.setLayoutManager(layoutManager);
        recyclerView.setHasFixedSize(true);

        apiInterface = ApiClient.getApiClient().create(ApiInterface.class);
        Call<List<Contact>> call = apiInterface.getContacts();
        call.enqueue(new Callback<List<Contact>>() {
            @Override
            public void onResponse(Call<List<Contact>> call, Response<List<Contact>> response) {
                contacts = response.body();

                recyclerView.setAdapter(adapter);
                adapter.notifyDataSetChanged();
            }

            @Override
            public void onFailure(Call<List<Contact>> call, Throwable t) {

            }
        });
    }
}
2
No adapter attached; skipping layout occurs everytimeMilan
Initialize contatcs. private List<Contact> contacts = new ArrayList<>();Aleksander Mielczarek

2 Answers

1
votes

I see some issues in the code.

1) your contactsvar is going un initialized inside the adapter.

2) You have set recyclerview inside onResponse method which is running in background thread.

Solution:

You need to initialize contacts and then give them values in onResponse method and set adapter on activity's runOnUiThread method.

Hope this code will help.

1) initialise contacts

private List<Contact> contacts = new ArrayList<>();

2) give expected values in onResponse method and initialize adapter there and remove initialization form onCreate method.

call.enqueue(new Callback<List<Contact>>() {
        @Override
        public void onResponse(Call<List<Contact>> call, Response<List<Contact>> response) {
            contacts = response.body();
            adapter = new RecyclerAdapter(contacts);
            runOnUiThread(() -> {
                recyclerView.setAdapter(adapter);
                adapter.notifyDataSetChanged();
            });

        }

        @Override
        public void onFailure(Call<List<Contact>> call, Throwable t) {

        }
2
votes

You forgot to initialize the arraylist

 private List<Contact> contacts;

then in onCreate() do this

contacts= new ArrayList<>();