数据更新后 RecyclerView 为空

RecyclerView empty after data update

我正在开发 Android 应用程序,该应用程序从服务器获取有关餐馆的信息并将其显示在 RecyclerView 中。当从服务器获取第一个信息包时,一切都按预期工作,但是,当我更改搜索条件并从服务器请求新信息包时,RecyclerView 变为空白。我使用 Toasts 来调试来自服务器的内容,我确信数据格式正确。此外,根据我的观察,用于接受数据的变量也在代码中得到了适当的处理。你可能知道为什么我的 RecyclerView 在应该显示第二个数据包时是空的?这是代码。

AfterLoginActivity.java

public class AfterLoginActivity extends AppCompatActivity {

/* interface main elements */
LinearLayout afterLoginLayout;
LinearLayout restaurantListLayout;
EditText restaurantEditText;
Button findRestaurantButton;
LoadingDialog loadingDialog;
AlphaAnimation loadingAnimation;
RecyclerView restaurantsRecyclerView;
int recycler_set = 0;
Button signOutButton;
GoogleSignInClient mGoogleSignInClient;
MyAdapter myAdapter = null;

/* server-client communication data */
public static String UploadUrl = "https://gdedakliknem.com/klopator.php";
public static String[] received;
String restaurants[] = new String[40];
String logos_as_strings[] = new String[40];
Bitmap logos[] = new Bitmap[40];
int num_of_elements = 0;
int data_received = 0;

/* user data */
String person_email;
String person_name;
String restaurant;

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

    /* interface main elements */
    afterLoginLayout = findViewById(R.id.afterLoginLayout);
    restaurantListLayout = findViewById(R.id.restaurantListLayout);
    restaurantEditText = findViewById(R.id.restaurantEditText);
    findRestaurantButton = findViewById(R.id.findRestaurantButton);
    restaurantsRecyclerView = findViewById(R.id.restaurantsRecyclerView);
    signOutButton = findViewById(R.id.signOutButton);
    loadingAnimation = new AlphaAnimation(1F, 0.8F);
    loadingDialog = new LoadingDialog(AfterLoginActivity.this);

    /* UPDATING INTERFACE ELEMENTS */

    /* execution thread */
    final Handler handler = new Handler();
    final int delay = 2000; // 1000 milliseconds == 1 second

    handler.postDelayed(new Runnable() {
        public void run() {

            /* check if recycler view is set */
            if(recycler_set == 0){
                /* if not, check if there is data to fil it with */
                if(data_received == 1){
                    /* convert received strings to images */
                    for(int i = 0; i < num_of_elements; i++){
                        logos[i] = stringToBitmap(logos_as_strings[i]);
                    }

                    /* fill interface elements */
                    loadingDialog.dismissDialog();
                    myAdapter = new MyAdapter(AfterLoginActivity.this, restaurants, logos, num_of_elements);
                    restaurantsRecyclerView.setAdapter(myAdapter);
                    restaurantsRecyclerView.setLayoutManager(new LinearLayoutManager(AfterLoginActivity.this));
                    afterLoginLayout.setVisibility(View.GONE);
                    restaurantListLayout.setVisibility(View.VISIBLE);
                    recycler_set = 1;
                }
            }
            handler.postDelayed(this, delay);
        }
    }, delay);

    /* catch restaurant name from user's entry */
    findRestaurantButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            restaurant = restaurantEditText.getText().toString();
            if(!restaurant.isEmpty()){
                view.startAnimation(loadingAnimation);
                loadingDialog.startLoadingDialog();
                sendRequest();
            } else{
                Toast.makeText(AfterLoginActivity.this, "Unesite naziv restorana!", Toast.LENGTH_LONG).show();
            }
        }
    });

    /* enable signing out */
    GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
            .requestEmail()
            .build();
    mGoogleSignInClient = GoogleSignIn.getClient(this, gso);
    signOutButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            switch (view.getId()) {
                case R.id.signOutButton:
                    signOut();
                    break;
            }
        }
    });

    /* obtaining email */
    GoogleSignInAccount acct = GoogleSignIn.getLastSignedInAccount(this);
    if (acct != null) {
        person_email = acct.getEmail();
        person_name = acct.getDisplayName();
    }
}

@Override
public void onBackPressed() {
    afterLoginLayout.setVisibility(View.VISIBLE);
    restaurantsRecyclerView.setVisibility(View.GONE);
    data_received = 0;
    recycler_set = 0;
}

private void signOut() {
    mGoogleSignInClient.signOut()
            .addOnCompleteListener(this, new OnCompleteListener<Void>() {
                @Override
                public void onComplete(@NonNull Task<Void> task) {
                    Toast.makeText(AfterLoginActivity.this, "Signed out", Toast.LENGTH_LONG).show();
                    finish();
                }
            });
}

public void sendRequest(){

    StringRequest stringRequest = new StringRequest(Request.Method.POST, UploadUrl, new Response.Listener<String>() {
        @Override
        public void onResponse(String response) {

            try {
                JSONObject jsonObject = new JSONObject(response);
                String Response = jsonObject.getString("response");
                if (Response.equals("Restaurant not found")){
                    loadingDialog.dismissDialog();
                    Toast.makeText(getApplicationContext(), "Uneti restoran ne postoji u sistemu! Proverite da li ste dobro napisali naziv", Toast.LENGTH_LONG).show();
                } else{
                    received = Response.split(";");
                    if (received.length > 0){
                        data_received = 1;
                        num_of_elements = received.length / 2;
                        //Toast.makeText(getApplicationContext(), "num of elements: " + num_of_elements, Toast.LENGTH_LONG).show();
                        for(int i = 0; i < num_of_elements; i++){
                            logos_as_strings[i] = received[i*2];
                            restaurants[i] = received[i*2+1];
                            //Toast.makeText(getApplicationContext(), "restaurants: " + restaurants, Toast.LENGTH_LONG).show();
                        }
                    } else{
                        loadingDialog.dismissDialog();
                        Toast.makeText(getApplicationContext(), "Greška u prijemu", Toast.LENGTH_LONG).show();
                    }
                }
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
    }, new Response.ErrorListener() {
        @Override
        public void onErrorResponse(final VolleyError error) {
            //volleyError = error;
        }
    })

    {
        @Override
        protected Map<String, String> getParams() throws AuthFailureError {

            //Toast.makeText(getApplicationContext(), "get params", Toast.LENGTH_LONG).show();

            Map<String, String> params = new HashMap<>();
            params.put("control", "find_restaurant");
            params.put("restaurant", restaurant);

            return params;
        }
    };

    RequestQueue requestQueue = Volley.newRequestQueue(AfterLoginActivity.this);
    requestQueue.add(stringRequest);
}

public static Bitmap stringToBitmap(String encodedString) {
    try {
        byte[] encodeByte = Base64.decode(encodedString, Base64.DEFAULT);
        return BitmapFactory.decodeByteArray(encodeByte, 0, encodeByte.length);

    } catch (Exception e) {
        e.getMessage();
        return null;
    }
}

MyAdapter.java

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

String restaurants[];
Bitmap logos[];
Context context;
int num_of_elements;

public MyAdapter(Context ct, String rests[], Bitmap lgs[], int num){
    context = ct;
    restaurants = rests;
    logos = lgs;
    num_of_elements = num;

    Toast.makeText(context, Integer.toString(restaurants.length), Toast.LENGTH_LONG).show();

    for(int i = 0; i < restaurants.length; i++){
        Toast.makeText(context, restaurants[i], Toast.LENGTH_SHORT).show();
    }
}

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

@Override
public void onBindViewHolder(@NonNull MyAdapter.MyViewHolder holder, int position) {
    holder.restaurantNameTextView.setText(restaurants[position]);
    holder.restaurantLogoImageView.setImageBitmap(logos[position]);
    holder.restaurantItemLayout.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Intent intent = new Intent(context, AfterPickingRestaurantActivity.class);
            ByteArrayOutputStream bs = new ByteArrayOutputStream();
            logos[position].compress(Bitmap.CompressFormat.PNG, 50, bs);
            intent.putExtra("byteArray", bs.toByteArray());
            intent.putExtra("picked_restaurant_name", restaurants[position]);
            context.startActivity(intent);
        }
    });
}

@Override
public int getItemCount() {
    /*
    int i = 0;
    if (restaurants != null){
        while(restaurants[i] != null){
            i++;
        }
    } else{
        i = restaurants.length;
    }

    return i;
    */
    return num_of_elements;
}

public class MyViewHolder extends RecyclerView.ViewHolder {

    TextView restaurantNameTextView;
    ImageView restaurantLogoImageView;
    LinearLayout restaurantItemLayout;

    public MyViewHolder(@NonNull View itemView) {
        super(itemView);
        restaurantNameTextView = itemView.findViewById(R.id.restaurantNameTextView);
        restaurantLogoImageView = itemView.findViewById(R.id.restaurantLogoImageView);
        restaurantItemLayout = itemView.findViewById(R.id.restaurantItemLayout);
    }
}

获取新数据后添加此行

myAdapter.notifyDataSetChanged()

您的适配器已在 OnCreate 方法中使用 RecyclerView 设置。

所以当你点击 findRestaurantButton 时,你只是从服务器获取 Resturent 数据,但收集的数据没有传入适配器,所以这就是为什么要获得空白适配器..

在数组中设置数据后,只需将此行放入 onResponse..

myAdapter.notifyDataSetChanged()

我发现哪里错了。如果你看一下重写后退按钮点击的部分,我错误地设置了 GONE recyclerView 本身:

restaurantsRecyclerView.setVisibility(View.GONE);

代替包含recyclerView的LinearLayout。期望的操作是:

restaurantListLayout.setVisibility(View.GONE);

P.S。在不调用 notifyDataSetChanged() 的情况下一切正常,我只是在每次收到新数据时创建一个新的 myAdapater 实例。我希望垃圾收集器正在做它的工作:)

谢谢大家的帮助!