Search code examples
androidwebsocketandroid-recyclerviewjava-websocket

TextView in RecyclerView is not showed up


I've been trying to fix my code for a long time. I looked so so many places to find a solution but no avail. If you look at my code and show me why my TextViews in RecylerView is not showed, that'd be great.

I am trying to use WebSocket-ing and fetch data from internet. That should be displayed in the RecyclerView in a constantly updated way. Data ledgers from ripple servers are coming with a natural delay. I want to show their some aspects in RecyclerView. All TextViews can change in content, they are just to try it out.

Here is my WebSocketActivity code:

package com.example.menes.searchcode.Websocketing;

import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

import com.example.menes.searchcode.R;
import com.google.gson.Gson;

import org.java_websocket.client.WebSocketClient;
import org.java_websocket.drafts.Draft;
import org.java_websocket.handshake.ServerHandshake;
import org.json.JSONObject;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class WebSocketActivity extends AppCompatActivity implements MyWebSocketAdapter.OnItemClickListener {

    private RecyclerView webSocketRecyclerView;// = findViewById(R.id.myRecyclerView);
    private MyWebSocketAdapter myWebSocketAdapter;
    List<LedgerResult> adapterLedgerResultList = new ArrayList<>();

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

        Button startWebsocketButton = findViewById(R.id.startButton);
        final Button stopWebSocketButton = findViewById(R.id.stopButton);

        startWebsocketButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                try {
                  if(adapterLedgerResultList.size() == 0)
                        Toast.makeText(WebSocketActivity.this,"Yes it is empty!, nice.",Toast.LENGTH_SHORT).show();

                    myWebSocketAdapter = new MyWebSocketAdapter(WebSocketActivity.this, adapterLedgerResultList);
                    webSocketRecyclerView = findViewById(R.id.myRecyclerView);
                    webSocketRecyclerView.setLayoutManager(new LinearLayoutManager(getApplicationContext()));
                    webSocketRecyclerView.setAdapter(myWebSocketAdapter);

                    final MySimpleClient c = new MySimpleClient( new URI( "wss://s2.ripple.com:443" ));
                    c.connect();

                    stopWebSocketButton.setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                         c.close();
                        }
                    });

                } catch (URISyntaxException e){
                    e.printStackTrace();
                    Toast.makeText(WebSocketActivity.this,"URISyntaxException occurred. Try again!",Toast.LENGTH_SHORT).show();
                }
            }
        });
    }

    public void bindIt () {

       //webSocketRecyclerView.setLayoutManager(new LinearLayoutManager(getApplicationContext()));

       myWebSocketAdapter.setOnItemClickListener(this);

       webSocketRecyclerView.setHasFixedSize(true);

        //webSocketRecyclerView.setAdapter(myWebSocketAdapter);
    }


    @Override
    public void onItemClick(int position) {

        Intent intent = new Intent(this, LedgerDisplayActivity.class);
        intent.putExtra("id", adapterLedgerResultList.get(position).getLedger_hash());
        startActivity(intent);

       //Toast.makeText(this,"Hey there, you onClicked!", Toast.LENGTH_SHORT).show();
    }

    public List<LedgerResult> addToadapterLedgerResultList (LedgerResult ledgerResult1){

        if(adapterLedgerResultList.size() != 0) {
            adapterLedgerResultList.add(ledgerResult1);

           /* myWebSocketAdapter.notifyItemInserted(adapterLedgerResultList.indexOf(ledgerResult1));
            webSocketRecyclerView.scrollToPosition(adapterLedgerResultList.indexOf(ledgerResult1));*/

            myWebSocketAdapter.notifyItemInserted(adapterLedgerResultList.size() - 1);
            //myWebSocketAdapter.notifyDataSetChanged();
            webSocketRecyclerView.scrollToPosition(adapterLedgerResultList.size() - 1);

            return adapterLedgerResultList;
        }
        else {
            adapterLedgerResultList.add(ledgerResult1);
            myWebSocketAdapter.notifyItemInserted(0);
           //myWebSocketAdapter.notifyDataSetChanged();
            return adapterLedgerResultList;
        }
    }


    public class MySimpleClient extends WebSocketClient {

        public MySimpleClient( URI serverUri , Draft draft ) {
            super( serverUri, draft );
        }

        public MySimpleClient( URI serverURI ) {
            super( serverURI );
        }

        public MySimpleClient( URI serverUri, Map<String, String> httpHeaders ) {
            super(serverUri, httpHeaders);
        }

        @Override
        public void onOpen( ServerHandshake handshakedata ) {
            send("{\n" +
                    "  \"id\": 1,\n" +
                    "  \"command\": \"subscribe\",\n" +
                    "  \"accounts\": [],\n" +
                    "  \"streams\": [\n" +
                    "    \"server\",\n" +
                    "    \"ledger\"\n" +
                    "  ]\n" +
                    "}");
            Log.d("SearchCode", "Connection opened!");
            // if you plan to refuse connection based on ip or httpfields overload: onWebsocketHandshakeReceivedAsClient
        }

        @Override
        public void onMessage(String message) {

            try {

                JSONObject obj = new JSONObject(message);

                Gson gson = new Gson();

                LedgerResult ledgerResult =  gson.fromJson(obj.toString(),LedgerResult.class);
                StreamExceptionHandler lilHandler = gson.fromJson(obj.toString(),StreamExceptionHandler.class);

                if(lilHandler.getBase_fee() != null){
                    //do nothing.
                }else {

                    adapterLedgerResultList = addToadapterLedgerResultList(ledgerResult);

                    if(adapterLedgerResultList.get(0).getLedger_index() == null){
                        LedgerResult tmp = adapterLedgerResultList.get(0);
                        adapterLedgerResultList.remove(tmp);
                        myWebSocketAdapter.notifyItemRemoved(0);
                       // myWebSocketAdapter.notifyDataSetChanged();
                    }
                    else {

                        bindIt();

                        Log.d("This is obj", obj.toString());
                        Log.d("LedgerResult", ledgerResult.toString());
                    }
                }

            } catch (Throwable t) {
                Log.e("SeachCode", "Could not parse malformed JSON: \"" + message + "\"");
            }

        }


        @Override
        public void onClose( int code, String reason, boolean remote ) {
            Log.e("SearchCode: ","Connection closed by " + ( remote ? "remote peer" : "us" ) + " Code: " + code + " Reason: " + reason);
        }

        @Override
        public void onError( Exception ex ) {
            ex.printStackTrace();
        }

    }
}

And my adapter code MyWebSocketAdapter is here:

package com.example.menes.searchcode.Websocketing;

import android.content.Context;
import android.graphics.Color;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import com.example.menes.searchcode.R;

import java.util.List;

public class MyWebSocketAdapter extends RecyclerView.Adapter<MyWebSocketAdapter.WebSocketView> {

    public interface OnItemClickListener {
        void onItemClick (int position);
    }

    private MyWebSocketAdapter.OnItemClickListener onItemClickListener;
    private Context context;
    private List<LedgerResult> adapterLedgerResultList;

    public MyWebSocketAdapter(Context context, List<LedgerResult> adapterLedgerResultList){
        this.context = context;
        this.adapterLedgerResultList = adapterLedgerResultList;
    }

    /*public MyWebSocketAdapter(Context context){
        this.context = context;
    }*/

    /*public List<LedgerResult> addToadapterLedgerResultList (LedgerResult ledgerResult1){

        adapterLedgerResultList.add(ledgerResult1);

       if(adapterLedgerResultList.size() != 0) {
            notifyItemInserted(adapterLedgerResultList.indexOf(ledgerResult1));
            return adapterLedgerResultList;
        }
        else {
            notifyItemInserted(0);
            return adapterLedgerResultList;
        }
    }*/

    public void setOnItemClickListener(MyWebSocketAdapter.OnItemClickListener onItemClickListener) {
        this.onItemClickListener = onItemClickListener;
    }

    class WebSocketView extends RecyclerView.ViewHolder {
        TextView otherThing;
        TextView hashCode, textView;

        public WebSocketView(View itemView) {

            super(itemView);

            hashCode =  itemView.findViewById(R.id.hashCode);
            otherThing = itemView.findViewById(R.id.otherThing);
            textView = itemView.findViewById(R.id.textView);
        }
    }

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

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

        final WebSocketView hldr = holder;

        LedgerResult row = adapterLedgerResultList.get(hldr.getAdapterPosition());

        if(row.getLedger_hash() == null) {
            holder.hashCode.setText("IT IS NULL");
        }
        else {
            holder.hashCode.setText(row.getLedger_hash());
            holder.hashCode.setTextColor(Color.parseColor("#239DEA"));
        }

        if(row.getLedger_index() == null) {
            holder.otherThing.setText("IT IS NULL");
        }
        else {
            holder.otherThing.setText(row.getLedger_index().toString());
        }


        if(row.getLedger_index() != null) {
            String s = row.getValidated_ledgers().toString();
            holder.textView.setText(s);
            //holder.textView.setVisibility(View.VISIBLE);
        }




       holder.itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if(onItemClickListener != null) {
                    onItemClickListener.onItemClick(hldr.getAdapterPosition());
                }
            }
        });
    }

   /* @Override
    public void onAttachedToRecyclerView(RecyclerView recyclerView) {
        super.onAttachedToRecyclerView(recyclerView);
    }*/

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

My XML files which I have also checked millions of times and even re-created.

websocket_and_button_thing.xml is:

<?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">

    <Button
        android:id="@+id/startButton"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginBottom="20dp"
        android:layout_marginEnd="8dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:text="Start"
        app:layout_constraintBottom_toTopOf="@+id/stopButton"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/myRecyclerView"
        app:layout_constraintVertical_bias="1.0" />

    <Button
        android:id="@+id/stopButton"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginBottom="4dp"
        android:layout_marginEnd="8dp"
        android:layout_marginStart="8dp"
        android:text="Stop"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintStart_toStartOf="parent" />

    <android.support.v7.widget.RecyclerView
        app:layoutManager="android.support.v7.widget.LinearLayoutManager"
        android:id="@+id/myRecyclerView"
        android:layout_width="368dp"
        android:layout_height="363dp"
        android:layout_marginEnd="8dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="4dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

    </android.support.v7.widget.RecyclerView>
</android.support.constraint.ConstraintLayout> 

And finally the inside-of-recyclerView code is called in-recycler.xml and it is:

<?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="wrap_content">

    <TextView
        android:id="@+id/textView"
        android:layout_width="94dp"
        android:layout_height="wrap_content"
        android:layout_marginBottom="8dp"
        android:layout_marginEnd="8dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:gravity="center_horizontal"
        android:text="TextView"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/hashCode" />

    <TextView
        android:id="@+id/hashCode"
        android:layout_width="261dp"
        android:layout_height="20dp"
        android:layout_marginBottom="8dp"
        android:layout_marginEnd="8dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="16dp"
        android:text="TextView"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toStartOf="@+id/otherThing"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.0" />

    <TextView
        android:id="@+id/otherThing"
        android:layout_width="0dp"
        android:layout_height="20dp"
        android:layout_marginBottom="8dp"
        android:layout_marginEnd="16dp"
        android:layout_marginTop="16dp"
        android:text="TextView"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.0" />

</android.support.constraint.ConstraintLayout>

Anyone is able to come up with a solution why TextViews are not showed up?

From the LOG records I can get all the data From debugging, my lists are working correct as well.

Note: I used the StreamExceptionHandler class to differentiate between two stream outcomes. One is useful to me, other is not and that's why I do not do anything if I catch anything.

Plus, my custom classes are working correctly since my lists seems to be well working.

AFTER EDIT:

I changed the WebSocketActivity and adapter as such. No so much changed. But now, again strangely, I am gettin all the data. It is added to RecyclerView too, but it does not show itself until I try to scroll manually. Plus, whenever a new data is arrived, RecyclerView completely disappears, then if I scroll again, it gets back with the updated data. ANY SOLUTION after update?


Solution

  • I guess, I found it. Since I changed the systematic and the code itself I cannot post the exact code to solve it but the key is overriding the runOnUiThread function within the button click. And you should change the RecyclerView binding and manager sets as well. Do it in a different place.

    To override the runOnUiThread in an anonymous (inner) class, use this:

     MainActivity.this.runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
    
                        }
                    });
    

    Hope this helps the future visitors.