英文:
Problems in Android FirebaseRecyclerView Implementing A Search Users Function
问题
我想要实现一个搜索功能。运行时,logcat 提示我:
> E/RecyclerView: 未附加适配器;跳过布局。
我在 Stack Overflow 和网络上搜索了答案,告诉我我需要设置适配器和线性布局管理器。从我的代码中您会看到,我已经都设置了。Alex Mamo(@AlexMamo)在这里的工作似乎指引我朝正确的方向前进,但我仍然遇到错误。
我的 Activity 类:
```java
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.TextView;
import android.widget.Toast;
import com.MyApp.Objects.ParticipantsObject;
import com.MyApp.R;
import com.firebase.ui.database.FirebaseRecyclerAdapter;
import com.firebase.ui.database.FirebaseRecyclerOptions;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.Query;
public class ParticipantsActivity extends AppCompatActivity {
// ... 这里省略了一些变量和方法 ...
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_neighbors);
// ... 这里省略了一些初始化操作 ...
mSearchBtn.setOnClickListener(view -> {
String searchText = mSearchField.getText().toString();
firebaseUserSearch(searchText);
});
}
// ... 这里省略了一些方法 ...
private void firebaseUserSearch(String searchText) {
Toast.makeText(ParticipantsActivity.this, "开始搜索", Toast.LENGTH_LONG).show();
Query firebaseSearchQuery = mUserDatabase.orderByChild("name").startAt(searchText);
FirebaseRecyclerOptions<ParticipantsObject> firebaseRecyclerOptions = new FirebaseRecyclerOptions.Builder<ParticipantsObject>()
.setQuery(firebaseSearchQuery, ParticipantsObject.class)
.build();
class UserHolder extends RecyclerView.ViewHolder {
// ... 这里省略了一些成员变量 ...
UserHolder(View itemView) {
super(itemView);
// ... 这里省略了一些初始化操作 ...
}
void setUsers(ParticipantsObject participantsObject) {
// ... 这里省略了一些操作 ...
}
}
FirebaseRecyclerAdapter<ParticipantsObject, UserHolder> firebaseRecyclerAdapter;
firebaseRecyclerAdapter = new FirebaseRecyclerAdapter<ParticipantsObject, UserHolder>(firebaseRecyclerOptions) {
@Override
protected void onBindViewHolder(@NonNull UserHolder userHolder, int position, @NonNull ParticipantsObject participantsObject) {
userHolder.setUsers(participantsObject);
}
@Override
public UserHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_layout, parent, false);
return new UserHolder(view);
}
};
mResultList.setAdapter(firebaseRecyclerAdapter);
firebaseRecyclerAdapter.startListening();
}
}
我的 Activity XML 文件:
<!-- ... 这里省略了一些布局内容 ... -->
我的列表布局文件:
<!-- ... 这里省略了一些布局内容 ... -->
希望这对您有所帮助。如果您有任何问题,请随时提问。
<details>
<summary>英文:</summary>
I'm looking to implement a search function. When it runs, logcat is telling me:
> E/RecyclerView: No adapter attached; skipping layout.
I have searched SO and the net and the answers tell me that I need to set the adapter and the linear layout manager. As you will see with my code, I set both. Alex Mamo's (@AlexMamo) work on here seems to point me in the right direction but I'm still getting the error.
My Activity
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.TextView;
import android.widget.Toast;
import com.MyApp.Objects.ParticipantsObject;
import com.MyApp.R;
import com.firebase.ui.database.FirebaseRecyclerAdapter;
import com.firebase.ui.database.FirebaseRecyclerOptions;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.Query;
public class ParticipantsActivity extends AppCompatActivity {
private EditText mSearchField;
private ImageButton mSearchBtn;
private RecyclerView mResultList;
private DatabaseReference mUserDatabase;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_neighbors);
mUserDatabase = FirebaseDatabase.getInstance().getReference().child("Users").child("Participants");
mSearchField = (EditText) findViewById(R.id.search_field);
mSearchBtn = (ImageButton) findViewById(R.id.search_btn);
mResultList = (RecyclerView) findViewById(R.id.result_list);
mResultList.setHasFixedSize(true);
mResultList.setLayoutManager(new LinearLayoutManager(this));
mSearchBtn.setOnClickListener(view -> {
String searchText = mSearchField.getText().toString();
firebaseUserSearch(searchText);
});
}
private void firebaseUserSearch(String searchText) {
Toast.makeText(ParticipantsActivity.this, "Started Search", Toast.LENGTH_LONG).show();
Query firebaseSearchQuery = mUserDatabase.orderByChild("name").startAt(searchText);
FirebaseRecyclerOptions<ParticipantsObject> firebaseRecyclerOptions = new FirebaseRecyclerOptions.Builder<ParticipantsObject>()
.setQuery(firebaseSearchQuery, ParticipantsObject.class)
.build();
class UserHolder extends RecyclerView.ViewHolder {
private TextView imageThumbTextView, nameTextView
UserHolder(View itemView) {
super(itemView);
imageThumbTextView = itemView.findViewById(R.id.profile_image);
nameTextView = itemView.findViewById(R.id.name_text);
}
void setUsers(ParticipantsObject participantsObject) {
String imageThumb = driverObject.getThumb_image();
imageThumbTextView.setText(imageThumb);
String name = participantsObject.getName();
nameTextView.setText(name);
}
}
FirebaseRecyclerAdapter<ParticipantsObject, UserHolder> firebaseRecyclerAdapter;
firebaseRecyclerAdapter = new FirebaseRecyclerAdapter<ParticipantsObject, UserHolder>(firebaseRecyclerOptions) {
@Override
protected void onBindViewHolder(@NonNull UserHolder userHolder, int position, @NonNull ParticipantsObject participantsObject) {
userHolder.setUsers(participantsObject);
}
@Override
public UserHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_layout, parent, false);
return new UserHolder(view);
}
};
mResultList.setAdapter(firebaseRecyclerAdapter);
firebaseRecyclerAdapter.startListening();
}
}
My Activity XML file
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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"
android:background="#ffffff"
tools:context="com.MyApp.ParticipantsActivity">
<TextView
android:id="@+id/heading_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_marginLeft="30dp"
android:layout_marginTop="30dp"
android:text="Firebase Search"
android:textColor="#555555"
android:textSize="24sp" />
<EditText
android:id="@+id/search_field"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignStart="@+id/heading_label"
android:layout_below="@+id/heading_label"
android:layout_marginRight="20dp"
android:layout_marginTop="20dp"
android:layout_toStartOf="@+id/search_btn"
android:background="@drawable/search_layout"
android:ems="10"
android:hint="Search here"
android:inputType="textPersonName"
android:paddingBottom="10dp"
android:paddingLeft="20dp"
android:paddingRight="20dp"
android:paddingTop="10dp"
android:textColor="#999999"
android:textSize="16sp" />
<ImageButton
android:id="@+id/search_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="@+id/search_field"
android:layout_alignParentEnd="true"
android:layout_alignTop="@+id/search_field"
android:layout_marginRight="30dp"
android:background="@android:color/background_light"
app:srcCompat="@mipmap/search_button" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/result_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/search_field"
android:layout_marginTop="50dp">
</androidx.recyclerview.widget.RecyclerView>
</RelativeLayout>
My list layout
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/profile_image"
android:layout_width="80dp"
android:layout_height="80dp"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_marginLeft="30dp"
android:layout_marginTop="20dp"
app:srcCompat="@mipmap/ic_default_user" />
<TextView
android:id="@+id/name_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_alignParentEnd="true"
android:layout_marginStart="14dp"
android:layout_marginLeft="20dp"
android:layout_marginTop="50dp"
android:layout_marginEnd="213dp"
android:layout_marginRight="20dp"
android:layout_toEndOf="@+id/profile_image"
android:text="Username"
android:textColor="#555555"
android:textSize="16sp" />
</RelativeLayout>
Any ideas or advice would be much appreciated.
</details>
# 答案1
**得分**: 1
你的代码是在按钮被点击后才设置适配器的。因为你没有在RecyclerView第一次需要在屏幕上渲染自身之前设置它,所以它会通过日志中的消息向你发出警告。在渲染时,RecyclerView必须附加一个适配器,以便显示任何内容。
<details>
<summary>英文:</summary>
Your code is setting the adapter only after a button is pushed. Because you didn't set it **before** the first time the RecyclerView needed to render itself on screen, it's going to warn you about that with the message you see in the log. The RecyclerView must have an adapter attached at the time of rendering in order for it to display anything.
</details>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论