2

I am getting the following error: "RecyclerView: No adapter attached; skipping layout" but I have attached the adapter... I have tried many different ways but I couldn't solve the error.

I am using Volley library to get data. When I launch the activity, only the progress bar is visible until the end, and I receive the Logcat message above. I have added the Recycleview with the adapter in the MainActivity. Could you please help me?

Here is my code:

MainActivity

public class MainActivity extends AppCompatActivity {
    private RequestQueue mRequestQueue;
    private ArrayList<Earthquake> mEarthquake;
    private RecyclerView mRecycleView;
    private EarthquakeAdapter adapter;
    
    boolean isConnected;
       
    TextView emptyView;
    ProgressBar loadingIndicator;
    
    private static final String USS_REQUEST_URL = "https://earthquake.usgs.gov/fdsnws/event/1/query";
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    
        final ConnectivityManager cm = (ConnectivityManager) this.getSystemService(Context.CONNECTIVITY_SERVICE);
    
        Read_network_state(cm);
    
        loadingIndicator = findViewById(R.id.loading_indicator);
        emptyView = findViewById(R.id.empty_view);
    
        mRecycleView = this.findViewById(R.id.recycle_list);
        mRecycleView.setHasFixedSize(true);
        LinearLayoutManager manager = new LinearLayoutManager(this);
        mRecycleView.setLayoutManager(manager);
        mEarthquake = new ArrayList<>();
    
        mRequestQueue = Volley.newRequestQueue(this);
    
        if (isConnected) {
            Uri uri = Uri.parse(USS_REQUEST_URL);
            Uri.Builder buider = uri.buildUpon();
    
            parseEarthquake(buider.toString());
        }
    }
    
    private void parseEarthquake(String key) {
        final JsonObjectRequest request = new JsonObjectRequest(Request.Method.GET, key.toString(), null, response -> {
            double magnitude = Double.parseDouble("");
            String location = "";
            long time = Long.parseLong("");
            String url = "";
    
            try {
                JSONArray feature = response.getJSONArray("feature");
                for (int i = 0; i < feature.length(); i++) {
                    JSONObject features = feature.getJSONObject(i);
                    JSONObject properties = features.getJSONObject("properties");
                    magnitude = properties.getDouble("mag");
                    location = properties.getString("place");
                    time = properties.getLong("time");
                    url = properties.getString("url");
                }
    
                Earthquake earthquake = new Earthquake(magnitude, location, time, url);
                mEarthquake.add(earthquake);
    
                adapter = new EarthquakeAdapter(MainActivity.this, mEarthquake);
                mRecycleView.setAdapter(adapter);
    
    
                Log.d("Ruhul", "No adapter");
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }, error -> {
            // Nothing
        });

        mRequestQueue.add(request);
    }

    public void Read_network_state(ConnectivityManager connectivityManager) {
        NetworkInfo activeNetwork = connectivityManager.getActiveNetworkInfo();
        if (activeNetwork != null && activeNetwork.isConnectedOrConnecting()) {
            isConnected = true;
            Log.d("Ruhul", "CONNECTED TO INTERNET");
        } else {
            isConnected = false;
        }
    }
}
    

EarthquakeAdapter

public class EarthquakeAdapter extends RecyclerView.Adapter<EarthquakeAdapter.MyViewHolder> {
    private Context mContext;
    private List<Earthquake> mData;
    
    public EarthquakeAdapter(Context mContext, List<Earthquake> mData) {
        this.mContext = mContext;
        this.mData = mData;
    }
    
    @NonNull
    @Override
    public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view;
        LayoutInflater inflater = LayoutInflater.from(mContext);
        view = inflater.inflate(R.layout.earthquake_raw, parent, false);
        final MyViewHolder viewHolder = new MyViewHolder(view);
    
        return viewHolder;
    }
    
    @Override
    public void onBindViewHolder(@NonNull MyViewHolder holder, int i) {
        Earthquake earthquake = mData.get(i);
        double earthquakeMagnitude = earthquake.getMagnitude();
    
        DecimalFormat decimalFormat = new DecimalFormat("0.0");
        String formattedMagnitude = decimalFormat.format(earthquakeMagnitude);
    
        holder.tvMagnitude.setText(formattedMagnitude);
    
        Date dateObject = new Date(earthquake.getTimeInMilliseconds());
        String formattedDate = formatDate(dateObject);
        holder.tvDate.setText(formattedDate);
    
        String formattedTime = formatTime(dateObject);
        holder.tvTime.setText(formattedTime);
    
        String originalLocation = earthquake.getLocation();
            
        holder.magnitudeCircle = (GradientDrawable) holder.tvMagnitude.getBackground();
    
        int magnitudecolor = getMagnitudeColor(earthquake.getMagnitude());
        holder.magnitudeCircle.setColor(magnitudecolor);
    
        if (originalLocation.contains("of")) {
            String[] parts = originalLocation.split("of");
            holder.tvLocationOffSet.setText(parts[0] + "of");
            holder.tvPrimaryLocation.setText(parts[1]);
        } else {
            holder.tvLocationOffSet.setText("Near The");
            holder.tvPrimaryLocation.setText(originalLocation);
        }
    }
    
    @Override
    public int getItemCount() {
        return mData.size();
    }
    
    public static class MyViewHolder extends RecyclerView.ViewHolder {
        TextView tvMagnitude, tvLocationOffSet, tvPrimaryLocation, tvDate, tvTime;
        LinearLayout container;
        GradientDrawable magnitudeCircle;
    
        public MyViewHolder(@NonNull View itemView) {
            super(itemView);
    
            tvMagnitude = itemView.findViewById(R.id.magnitude);
            tvLocationOffSet = itemView.findViewById(R.id.location_offset);
            tvPrimaryLocation = itemView.findViewById(R.id.primary_location);
            tvDate = itemView.findViewById(R.id.date);
            tvTime = itemView.findViewById(R.id.time);
            container = itemView.findViewById(R.id.container);
        }
    }
    
    /**
     * Return the color of the magitude circle based on the intensity of the earthquake.
     *
     * @param magnitude of the earthquake
     */
    private int getMagnitudeColor(double magnitude) {
        int magnitudeColorResourceId;
        int magnitudeFloor = (int) Math.floor(magnitude);
        switch (magnitudeFloor) {
            case 0:
            case 1:
                magnitudeColorResourceId = R.color.magnitude1;
                break;
    
            case 2:
                magnitudeColorResourceId = R.color.magnitude2;
                break;
    
            case 3:
                magnitudeColorResourceId = R.color.magnitude3;
                break;
    
            case 4:
                magnitudeColorResourceId = R.color.magnitude4;
                break;
    
            case 5:
                magnitudeColorResourceId = R.color.magnitude5;
                break;
    
            case 6:
                magnitudeColorResourceId = R.color.magnitude6;
                break;
    
            case 7:
                magnitudeColorResourceId = R.color.magnitude7;
                break;
    
            case 8:
                magnitudeColorResourceId = R.color.magnitude8;
                break;
    
            case 9:
                magnitudeColorResourceId = R.color.magnitude9;
                break;
    
            default:
                magnitudeColorResourceId = R.color.magnitude10plus;
                break;
        }
    
        return ContextCompat.getColor(mContext, magnitudeColorResourceId);
    }
    
    private String formatDate(Date dateObject) {
        SimpleDateFormat dateFormat = new SimpleDateFormat("LLL dd, yyyy");

        return dateFormat.format(dateObject);
    }
    
    private String formatTime(Date dateObject) {
        SimpleDateFormat timeFormat = new SimpleDateFormat("h:mm a");

        return timeFormat.format(dateObject);
    }
}
    

MainActivity.xml

<?xml version="1.0" encoding="utf-8"?>

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    xmlns:tools="http://schemas.android.com/tools">
        
    <TextView 
        android:id="@+id/empty_view" 
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content" 
        android:layout_centerInParent="true" 
        android:textAppearance="?android:textAppearanceMedium"/>

    <androidx.recyclerview.widget.RecyclerView 
        android:id="@+id/recycle_list" 
        android:layout_width="match_parent" 
        android:layout_height="match_parent" 
        android:orientation="vertical" 
        tools:listitem="@layout/earthquake_raw"/>
        
    <ProgressBar 
        android:id="@+id/loading_indicator" 
        style="@style/Widget.AppCompat.ProgressBar" 
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content" 
        android:layout_centerInParent="true"/>
</RelativeLayout>

EarthquakeRaw.xml

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="150dp"
    android:orientation="horizontal"
    android:paddingStart="16dp"
    android:paddingLeft="16dp"
    android:paddingEnd="16dp"
    android:paddingRight="16dp">
    <TextView
        android:id="@+id/magnitude"
        android:layout_width="36dp"
        android:layout_height="36dp"
        android:layout_gravity="center_vertical"
        android:background="@drawable/magnitude_circle"
        android:fontFamily="sans-serif-medium"
        android:gravity="center"
        android:textColor="@android:color/black"
        android:textSize="16sp"
        tools:text="8.9" />

    <LinearLayout
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical"
        android:layout_marginStart="16dp"
        android:layout_marginLeft="16dp"
        android:layout_weight="1"
        android:orientation="vertical">
        <TextView
            android:id="@+id/location_offset"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:ellipsize="end"
            android:fontFamily="sans-serif-medium"
            android:maxLines="1"
            android:textAllCaps="true"
            android:textColor="@android:color/black"
            android:textSize="12sp"
            tools:text="30km S of" />

        <TextView
            android:id="@+id/primary_location"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:ellipsize="end"
            android:maxLines="2"
            android:textColor="@android:color/black"
            android:textSize="12sp"
            tools:text="Long placeholder that should wrap to more than 2 line of text" />
    </LinearLayout>

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical"
        android:layout_marginStart="16dp"
        android:layout_marginLeft="16dp"
        android:orientation="vertical">
        <TextView
            android:id="@+id/date"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="end"
            android:textColor="@color/textColorEarthquakeDetails"
            android:textSize="12sp"
            tools:text="Mar 6, 2010" />

        <TextView
            android:id="@+id/time"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="end"
            android:textColor="@color/textColorEarthquakeDetails"
            android:textSize="12sp"
            tools:text="3:00 PM" />
    </LinearLayout>
</LinearLayout>
Abhinav Suman
  • 940
  • 1
  • 9
  • 29
Ruhul
  • 53
  • 10

2 Answers2

1

Always try to attach the adapter in main UI thread, or outside your asynchronous task. Also, you can add this code in oncreate(). and when mEarthquake arraylist is populated, call adapter.notifydatasetchanged().

adapter = new EarthquakeAdapter(MainActivity.this, mEarthquake);
            mRecycleView.setAdapter(adapter); 
Asad khan
  • 156
  • 7
0

You should add data to model inside for loop.
Try like below will work fine,

JSONArray feature = response.getJSONArray("feature");
    for (int i = 0; i < feature.length(); i++) {
        JSONObject features = feature.getJSONObject(i);
        JSONObject properties = features.getJSONObject("properties");
        magnitude = properties.getDouble("mag");
        location = properties.getString("place");
        time = properties.getLong("time");
        url = properties.getString("url");
        Earthquake earthquake = new Earthquake(magnitude, location, time, url);
        mEarthquake.add(earthquake);
        adapter = new EarthquakeAdapter(MainActivity.this, mEarthquake);
        mRecycleView.setAdapter(adapter);
        adapter.notifyDatasetChanged();
    }
G Ganesh
  • 103
  • 7