android studio CoordinatorLayout & RecyclerView bl

2019-09-10 21:00发布

问题:

Runing my app i get a blank activity, for the time being i only have a list which should be projecting images, by reading these images addresses from JSON, and from the logcat i could see the the addresses being passed to the app, and logged, but not sure why the layout is not getting structured and i get a blank white screen.

Using Genymotion - android s6 - android studio 2.1.1

MyActivity;

  import java.util.ArrayList;
  import java.util.Collection;
  import java.util.HashMap;
  import java.util.Map;


  public class MainActivity extends AppCompatActivity {

ArrayList<String> image_urls = new ArrayList<String>();
String[] android_image_urls = new String[image_urls.size()];


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Firebase.setAndroidContext(this);
    ImagesAddresses();
    initViews();

}
public void ImagesAddresses(){
    Firebase ref = new Firebase("https://xxxxx.firebaseio.com/xxxxxx/xxx");
    ref.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot snapshot) {
            Map<String, String> allADR = (HashMap<String, String>) snapshot.getValue();
            if (allADR != null) {
                Collection<String> BlkADR = allADR.values();

                image_urls.addAll(BlkADR);
                android_image_urls = image_urls.toArray(android_image_urls);

                    Log.i("myTag", image_urls.toString());

            }
        }

        @Override
        public void onCancelled(FirebaseError firebaseError) {

        }
    });
}

private void initViews(){
    RecyclerView recyclerView = (RecyclerView)findViewById(R.id.card_recycler_view);
    recyclerView.setHasFixedSize(true);
    RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getApplicationContext());
    recyclerView.setLayoutManager(layoutManager);

    ArrayList androidVersion = prepareData();
    DataAdapter adapter = new DataAdapter(getApplicationContext(),androidVersion);
    recyclerView.setAdapter(adapter);

}
private ArrayList prepareData(){

    ArrayList android_version = new ArrayList<>();
    for(int i=0;i<android_image_urls.length;i++){
        AndroidVersion androidVersion = new AndroidVersion();
        androidVersion.setAndroid_image_url(android_image_urls[i]);
        android_version.add(androidVersion);
    }
    return android_version;
}
 }

activity_main.xml;

   <?xml version="1.0" encoding="utf-8"?>
  <android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<android.support.v7.widget.RecyclerView
    android:id="@+id/card_recycler_view"
    android:scrollbars="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>

  </android.support.design.widget.CoordinatorLayout>

DataAdapter.java;

  package net.janusjanus.interactive_layout;


 import android.content.Context;
 import android.support.v7.widget.RecyclerView;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.ImageView;

 import com.squareup.picasso.Picasso;

 import java.util.ArrayList;

 public class DataAdapter extends RecyclerView.Adapter<DataAdapter.ViewHolder> {
private ArrayList<AndroidVersion> android_version;
private Context context;

public DataAdapter(Context context,ArrayList<AndroidVersion> android_version) {
    this.context = context;
    this.android_version = android_version;

}

@Override
public DataAdapter.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
    View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.row_layout, viewGroup, false);
    return new ViewHolder(view);
}

@Override
public void onBindViewHolder(ViewHolder viewHolder, int i) {

    Picasso.with(context).load(android_version.get(i).getAndroid_image_url()).resize(120, 60).into(viewHolder.img_android);
}

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

public class ViewHolder extends RecyclerView.ViewHolder{
    ImageView img_android;
    public ViewHolder(View view) {
        super(view);

        img_android = (ImageView)view.findViewById(R.id.img_android);
    }
}
}

AndroidVersion.java;

   package net.janusjanus.interactive_layout;


 public class AndroidVersion {

private String android_image_url;


public String getAndroid_image_url() {
    return android_image_url;
}

public void setAndroid_image_url(String android_image_url) {
    this.android_image_url = android_image_url;
}
}

going over the error i got the followin;

  05-15 04:19:57.942 7827-7875/net.janusjanus.interactive_layout I/OpenGLRenderer: Initialized EGL, version 1.4
 05-15 04:19:58.055 7827-7875/net.janusjanus.interactive_layout W/EGL_emulation: eglSurfaceAttrib not implemented
 05-15 04:19:58.056 7827-7875/net.janusjanus.interactive_layout W/OpenGLRenderer: Failed to set EGL_SWAP_BEHAVIOR on surface 0xe7d65fe0, error=EGL_SUCCESS
 05-15 04:20:01.188 7827-7827/net.janusjanus.interactive_layout I/myTag: [http://res.cloudinary.com/xxxxx/image/xxxxxx/xxxxxx/fw88v6xu6wybamg9zzt6.jpg, http://res.cloudinary.com/xxxx/image/upload/xxxxx/xxxxdgfddd.jpg, http://res.cloudinary.com/xxxxxxx/jjjjjj/upload/xxxxxxxx/vvvghgggggg.jpg]

DataAdapter.java; and i have searched stackoverflow for eglSurfaceAttrib not implemented

increased the emulator disk size, implemented Gapp and other instructions i found on the following posts; Android Studio - Emulator - eglSurfaceAttrib not implemented

but still no layout.

As the user below suggested, i changed the initialization of initView, into the end of ImageAddresses, in order for it to follow the step of retrieving the addresses, and also logged the android_version.size(); which returns zero, thus the layout is still blank but not sure how to fix this problem,

Logcat after changes ;

   05-15 05:59:25.025 3473-3537/net.janusjanus.interactive_layout I/OpenGLRenderer: Initialized EGL, version 1.4
  05-15 05:59:25.174 3473-3537/net.janusjanus.interactive_layout W/EGL_emulation: eglSurfaceAttrib not implemented
  05-15 05:59:25.174 3473-3537/net.janusjanus.interactive_layout W/OpenGLRenderer: Failed to set EGL_SWAP_BEHAVIOR on surface 0xe08c47a0, error=EGL_SUCCESS
 05-15 05:59:25.253 3473-3473/net.janusjanus.interactive_layout I/myTag: 0
 05-15 05:59:25.253 3473-3473/net.janusjanus.interactive_layout I/myTag: 0
 05-15 05:59:25.655 3473-3473/net.janusjanus.interactive_layout I/myTag: 0
 05-15 05:59:25.656 3473-3473/net.janusjanus.interactive_layout I/myTag: 0
 05-15 05:59:25.656 3473-3473/net.janusjanus.interactive_layout I/myTag: 0

Apparently the cause of this error is a conflict in timing in executing methods, thus as suggested by of you i am trying to user runOnUiThread, which i am not sure how to construct properly within my code, so far i've tried the following in my MainActivity;

  public class MainActivity extends AppCompatActivity {

ArrayList<String> image_urls = new ArrayList<String>();
String[] android_image_urls = new String[image_urls.size()];


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Firebase.setAndroidContext(this);
    ImagesAddresses();

}
public void ImagesAddresses(){
    Firebase ref = new Firebase("https://xxxxx.firebaseio.com/xxxxx/xxxxx");
    ref.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot snapshot) {
            Map<String, String> allADR = (HashMap<String, String>) snapshot.getValue();
            if (allADR != null) {
                Collection<String> BlkADR = allADR.values();

                image_urls.addAll(BlkADR);
                android_image_urls = image_urls.toArray(android_image_urls);

// private final String android_image_urls[]=android_image_urls

                    Log.i("myTag", image_urls.toString());

                initViews();


            }
        }

        @Override
        public void onCancelled(FirebaseError firebaseError) {

        }
    });


}

private void initViews(){

    runOnUiThread(new Runnable() {
        public void run() {
            //Do something on UiThread

            RecyclerView recyclerView = (RecyclerView)findViewById(R.id.card_recycler_view);
            recyclerView.setHasFixedSize(true);
            RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getApplicationContext());
            recyclerView.setLayoutManager(layoutManager);

            ArrayList androidVersion = prepareData();
            DataAdapter adapter = new DataAdapter(getApplicationContext(),androidVersion);
            recyclerView.setAdapter(adapter);

        }
    });


}
private ArrayList prepareData(){

    ArrayList android_version = new ArrayList<>();
    for(int i=0;i<android_image_urls.length;i++){
        AndroidVersion androidVersion = new AndroidVersion();
        androidVersion.setAndroid_image_url(android_image_urls[i]);
        android_version.add(androidVersion);
    }
    return android_version;
}

} But i guess it is not the right way to do it, since the app still crash - and i get the following errors;

    05-15 07:11:34.935 11327-11327/net.janusjanus.interactive_layout E/AndroidRuntime: FATAL EXCEPTION: main
                                                                               Process: net.janusjanus.interactive_layout, PID: 11327
                                                                               java.lang.NullPointerException: Attempt to invoke virtual method 'boolean android.support.v7.widget.RecyclerView$LayoutManager.canScrollVertically()' on a null object reference
                                                                                   at android.support.v7.widget.RecyclerView.computeVerticalScrollRange(RecyclerView.java:1654)
                                                                                   at android.view.View.onDrawScrollBars(View.java:13924)
                                                                                   at android.view.View.onDrawForeground(View.java:17657)
                                                                                   at android.view.View.draw(View.java:16189)
                                                                                   at android.support.v7.widget.RecyclerView.draw(RecyclerView.java:3097)
                                                                                   at android.view.View.updateDisplayListIfDirty(View.java:15174)
                                                                                   at android.view.View.draw(View.java:15948)
                                                                                   at android.view.ViewGroup.drawChild(ViewGroup.java:3609)
                                                                                   at android.support.design.widget.CoordinatorLayout.drawChild(CoordinatorLayout.java:1077)
                                                                                   at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3399)
                                                                                   at android.view.View.draw(View.java:16181)
                                                                                   at android.view.View.updateDisplayListIfDirty(View.java:15174)
                                                                                   at android.view.View.draw(View.java:15948)
                                                                                   at android.view.ViewGroup.drawChild(ViewGroup.java:3609)
                                                                                   at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3399)
                                                                                   at android.view.View.updateDisplayListIfDirty(View.java:15169)
                                                                                   at android.view.View.draw(View.java:15948)
                                                                                   at android.view.ViewGroup.drawChild(ViewGroup.java:3609)
                                                                                   at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3399)
                                                                                   at android.view.View.updateDisplayListIfDirty(View.java:15169)
                                                                                   at android.view.View.draw(View.java:15948)
                                                                                   at android.view.ViewGroup.drawChild(ViewGroup.java:3609)
                                                                                   at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3399)
                                                                                   at android.view.View.updateDisplayListIfDirty(View.java:15169)
                                                                                   at android.view.View.draw(View.java:15948)
                                                                                   at android.view.ViewGroup.drawChild(ViewGroup.java:3609)
                                                                                   at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3399)
                                                                                   at android.view.View.updateDisplayListIfDirty(View.java:15169)
                                                                                   at android.view.View.draw(View.java:15948)
                                                                                   at android.view.ViewGroup.drawChild(ViewGroup.java:3609)
                                                                                   at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3399)
                                                                                   at android.view.View.draw(View.java:16181)
                                                                                   at com.android.internal.policy.PhoneWindow$DecorView.draw(PhoneWindow.java:2690)
                                                                                   at android.view.View.updateDisplayListIfDirty(View.java:15174)
                                                                                   at android.view.ThreadedRenderer.updateViewTreeDisplayList(ThreadedRenderer.java:281)
                                                                                   at android.view.ThreadedRenderer.updateRootDisplayList(ThreadedRenderer.java:287)
                                                                                   at android.view.ThreadedRenderer.draw(ThreadedRenderer.java:322)
                                                                                   at android.view.ViewRootImpl.draw(ViewRootImpl.java:2615)
                                                                                   at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:2434)
                                                                                   at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2067)
                                                                                   at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1107)
                                                                                   at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6013)
                                                                                   at android.view.Choreographer$CallbackRecord.run(Choreographer.java:858)
                                                                                   at android.view.Choreographer.doCallbacks(Choreographer.java:670)
                                                                                   at android.view.Choreographer.doFrame(Choreographer.java:606)
                                                                                   at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:844)
                                                                                   at android.os.Handler.handleCallback(Handler.java:739)
                                                                                   at android.os.Handler.dispatchMessage(Handler.java:95)
                                                                                   at android.os.Looper.loop(Looper.java:148)
                                                                                   at android.app.ActivityThread.main(ActivityThread.java:5417)
                                                                                   at java.lang.reflect.Method.invoke(Native Method)
                                                                                   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
                                                                                   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

回答1:

In ImagesAddresses(); you are using Firebase to retrieve the data from your webservice, and you get the results through the delegate method onDataChange. Since the execution of this method is asynchronous, what happens is that initViews(); and, therefore prepareData(), are called before onDataChange is called. As you can image android_image_urls is still empty. What you have to do to fix is to call initViews(); from onDataChange, making sure that it, initViews();, runs on the UI Thread.