I've seen lots of these questions, but I don't have any child elements so I don't know why this isn't working properly. I moved this to a fragment from an activity and it's no longer working. I saw previous questions have issues with having child elements from the recyclerview but that's not the case here. Here's my code:
public class TodoListFragment extends Fragment {
@BindView(R.id.todo_recycler_view)
protected RecyclerView mRecyclerView;
@BindView(R.id.fab)
protected FloatingActionButton mFab;
private TodoListAdapter mTodoListAdapter;
private RecyclerView.LayoutManager mLayoutManager;
public static TodoListFragment newInstance() {
return new TodoListFragment();
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.todo_list_recycler_view, container, false);
ButterKnife.bind(this, view);
mRecyclerView.setHasFixedSize(true);
mLayoutManager = new LinearLayoutManager(getActivity());
mRecyclerView.setLayoutManager(mLayoutManager);
mTodoListAdapter = new TodoListAdapter();
mRecyclerView.setAdapter(mTodoListAdapter);
return view;
}
@OnClick(R.id.fab)
public void onAdd() {
TodoItemView todoItemView = new TodoItemView(getContext());
todoItemView.setText("Schedule a dentist's appointment");
todoItemView.setTime(new Date());
mTodoListAdapter.addItem(todoItemView);
}
}
And here's the todo_list_recycler_view.xml:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.RecyclerView 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:id="@+id/todo_recycler_view"
android:scrollbars="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:context=".presentation.TodoActivity"
tools:showIn="@layout/activity_todo_list" />
Any idea why I'm getting this error?
Caused by: java.lang.IllegalStateException: RecyclerView has no LayoutManager
at android.support.v7.widget.RecyclerView.generateLayoutParams(RecyclerView.java:3393)
at android.view.LayoutInflater.inflate(LayoutInflater.java:502)
at android.view.LayoutInflater.inflate(LayoutInflater.java:423)
at com.vorple.shortlist.shortlist.presentation.TodoListFragment.onCreateView(TodoListFragment.java:44)
Consider moving this line
mRecyclerView.setHasFixedSize(true);
after the line where you assign the layout manager to the recycler view. You may need the layout manager declared before you can call setHasFixedSize
尝试在另一个方法重写中添加recyclerview管理器,Butterknife和对象可能正在工作,将布局管理器添加到onResume中或需要加载数据时会发生什么情况。
I am very confuse with what you want to achieve with TodoItemView
( link ) class. Inside init()
method, you are inflating another view which I assumed you want to use this class to display the item in list. The problem arise inside this class which, based on your logic, every time you add a model, you will re-inflate the view. It supposed to be inflated once, then store the reference and simply grab back the view when you add another item. In this case, I don't think recyclerView capable to recycle your view.
So, I have recreated a scenario and simplified your code. But I am not sure if this is the exact solution of your problem. But, maybe you can find something useful here.
1) Activity
public class MainActivity extends AppCompatActivity{
private Button playBtn, startActivityBtn;
private MediaPlayer mediaPlayer;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getSupportFragmentManager().beginTransaction()
.add(R.id.mainContent, new TododFragment())
.commit();
}
}
2) Fragment
public class TododFragment extends Fragment {
private RecyclerView mRecyclerView;
private RecyclerView.LayoutManager mLayoutManager;
private TodoListAdapter mTodoListAdapter;
public TododFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_todod, container, false);
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mRecyclerView = (RecyclerView)view.findViewById(R.id.todo_recycler_view);
mRecyclerView.setHasFixedSize(true);
mLayoutManager = new LinearLayoutManager(getActivity());
mRecyclerView.setLayoutManager(mLayoutManager);
mTodoListAdapter = new TodoListAdapter();
mRecyclerView.setAdapter(mTodoListAdapter);
//Create 10 dummies data
SimpleDateFormat dt = new SimpleDateFormat("h:mm a");
for(int i = 0; i < 10; i++){
if(i % 2 == 0)
mTodoListAdapter.addItem(new TodoItem("Schedule a dentist's appointment", dt.format(new Date()), 0));
else
mTodoListAdapter.addItem(new TodoItem("Schedule a dentist's appointment", dt.format(new Date()), 1));
}
}
}
3) Model
public class TodoItem {
private String text;
private String time;
//LayoutType is used to display different layout.
private int layoutType;
public TodoItem(String text, String time, int layoutType) {
this.text = text;
this.time = time;
this.layoutType = layoutType;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public String getTime() {
return time;
}
public void setTime(String time) {
this.time = time;
}
public int getLayoutType() {
return layoutType;
}
public void setLayoutType(int layoutType) {
this.layoutType = layoutType;
}
}
4) Adapter (In this case, I have two layout. If you want to use one layout, remove getItemViewType
)
public class TodoListAdapter extends RecyclerView.Adapter<TodoListAdapter.TodoItemViewHolder> {
private List<TodoItem> mItems;
public static class TodoItemViewHolder extends RecyclerView.ViewHolder{
public TextView mTextViewText;
public TextView mTextViewTime;
public TodoItemViewHolder(View itemView) {
super(itemView);
mTextViewText = (TextView)itemView.findViewById(R.id.mTextViewText);
mTextViewTime = (TextView)itemView.findViewById(R.id.mTextViewTime);
}
}
public TodoListAdapter() {
mItems = new ArrayList<>();
}
@Override
public int getItemViewType(int position) {
//ItemViewType will return an int for every row. You can use this to control with layout you want to display
return mItems.get(position).getLayoutType();
}
@Override
public TodoItemViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
//get the viewType and display the layout accordingly
View view = null;
if(viewType == 0){
view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.todo_list_item, parent, false);
}
else{
view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.todo_list_item2, parent, false);
}
TodoItemViewHolder rcv = new TodoItemViewHolder(view);
return rcv;
}
@Override
public void onBindViewHolder(TodoItemViewHolder holder, int position) {
holder.mTextViewText.setText(mItems.get(position).getText());
holder.mTextViewTime.setText(mItems.get(position).getTime());
}
@Override
public int getItemCount() {
return mItems.size();
}
public void addItem(TodoItem item) {
mItems.add(item);
notifyItemInserted(mItems.size() - 1);
}
}
I figured out the cause of the exception.
Here is what I changed within my activity's XML file:
<!-- <include layout="@layout/todo_list_recycler_view" /> -->
<FrameLayout
android:id="@+id/todo_list_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
Instead of including @layout/todo_list_recycler_view in the activity's layout file, I just replaced the empty FrameLayout with todo_list_recycler_view when instantiating my fragment and that gets rid of the exception. I'm not sure why this is the case but it solves the issue for me.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.