RecyclerView:没有附加适配器;使用改造跳过应用程序中的布局[重复]

Posted

技术标签:

【中文标题】RecyclerView:没有附加适配器;使用改造跳过应用程序中的布局[重复]【英文标题】:RecyclerView: No adapter attached; skipping layout in app using retrofit [duplicate] 【发布时间】:2019-02-18 23:11:05 【问题描述】:

我有一个连接到 API 并从中获取一些数据的简单程序。我使用 Retrofit 库。有两个活动。 MainActivity 包括一个 RecyclerView,它显示从服务器接收到的数据。如果按任何项目,应用程序转到UserInfoActivity 并显示该项目的详细信息。我的应用程序在转到UserInfoActivity 几秒钟后崩溃并且不显示信息。然而response 正确接收但程序给出错误 在txtId.setText(user.getId) 线上。错误是E/RecyclerView: No adapter attached; skipping layout 事实上,我的问题是在第二个 Activity 中调用 Call<User> getUserInfo(@Path("id") int id); 时开始的。

这是MainActivity 代码。

 protected void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    userRequest();


private void userRequest()
    APIInterface apiInterface= APIClient.getClient().create(APIInterface.class);
    retrofit2.Call<ArrayList<User>> call= apiInterface.getUsers();
    call.enqueue(new Callback<ArrayList<User>>() 
        @Override
        public void onResponse(retrofit2.Call<ArrayList<User>> call, Response<ArrayList<User>> response) 
            if(response.isSuccessful())
                ArrayList<User> users = response.body();
                setupRecycelerView(users);
            
        
        @Override
        public void onFailure(retrofit2.Call<ArrayList<User>> call, Throwable t) 
            Log.i("RETROFIT","response not successful");
        
    );


private void setupRecycelerView(ArrayList<User> users)
    recyclerView=findViewById(R.id.RcyView);
    adapter=new RecycelerAdapter(this,users);
    linearLayoutManager=new LinearLayoutManager(this,LinearLayoutManager.VERTICAL,false);
    recyclerView.setAdapter(adapter);
    recyclerView.setHasFixedSize(true);
    recyclerView.setLayoutManager(linearLayoutManager);
    recyclerView.setItemAnimator(new DefaultItemAnimator());


这是RecycelerAdapteronBindViewHolder 函数。

 public void onBindViewHolder(@NonNull UserViewHolder holder, int position) 
    final User user=values.get(position);
    holder.txtName.setText(user.getName());
    holder.txtPhone.setText(user.getPhone());
    final Intent intent=new Intent(context, UserInfoActivity.class);
    intent.putExtra("user",user);
    holder.root.setOnClickListener(new View.OnClickListener() 
        @Override
        public void onClick(View v) 
            context.startActivity(intent);
        
    );

这是UserInfoActivity 代码。

 protected void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_user_info);
    txtId=findViewById(R.id.txtId);
    txtName=findViewById(R.id.txtName);
    txtPhone=findViewById(R.id.txtPhone);
    Intent intent=getIntent();
    User user=(User)intent.getSerializableExtra("user");
    id=user.getId();
    userInfoRequest();

private void userInfoRequest()
    APIInterface apiInterface= APIClient.getClient().create(APIInterface.class);
    retrofit2.Call<User> call= apiInterface.getUserInfo(id);
    call.enqueue(new Callback<User>() 
        @Override
        public void onResponse(Call<User> call, Response<User> response) 
            if(response.isSuccessful())
                User user=response.body();
                Log.e("MF","ON Response");
                Log.e("MF",user.getName());
                Log.e("MF",user.getPhone());
                txtId.setText(user.getId());
                txtName.setText(user.getName());
                txtPhone.setText(user.getPhone());
            
        
        @Override
        public void onFailure(Call<User> call, Throwable t) 
            Log.e("MF","on failure");
        
    );


【问题讨论】:

请发布完整的错误堆栈跟踪@sarina 【参考方案1】:

试试这个:

linearLayoutManager=new LinearLayoutManager(this,LinearLayoutManager.VERTICAL,false);
recyclerView.setLayoutManager(linearLayoutManager);
adapter=new RecycelerAdapter(this,users);
recyclerView.setAdapter(adapter);
adapter.notifyDataSetChanged();
recyclerView.setHasFixedSize(true);
recyclerView.setItemAnimator(new DefaultItemAnimator());

使用notifyDataSetChanged() 告诉RecyclerView 数据已更改-添加并在setLayoutManager 之后设置Adapter


如果这没有帮助,请在 onCreate 方法中初始化 RecyclerView 并在 onResponse 中设置 AdapterrunOnUiThread,如下所示:

runOnUiThread(new Runnable() 
                    @Override
                    public void run() 
                    //Do something on UiThread
                   ArrayList<User> users = response.body();
                   adapter=new RecycelerAdapter(this,users);
                   recyclerView.setAdapter(users);
                
            );

然后调用notifyDataSetChanged(),它应该可以工作。

【讨论】:

我每四个答案做一次,但我的问题还没有解决! 因此,在onCreate 方法中初始化RecyclerView,并在ArrayList&lt;User&gt; users = response.body(); 之后将Adapter 设置为ArrayList&lt;User&gt; users = response.body();runOnUiThread。那时它会起作用的。我已经更新了答案。 不幸的是,同样的错误重复出现。 E/androidRuntime: FATAL EXCEPTION: main Process: com.example.np.retrofitarcademy, PID: 14983 android.content.res.Resources$NotFoundException: String resource ID #0x4 at android.content.res.Resources.getText(Resources.java:1468) at android.widget.TextView.setText(TextView.java:5051) at com.example.np.retrofitarcademy.UserInfoActivity$1.onResponse(UserInfoActivity.java:50) 哦,这实际上是另一个问题,你会在你的问题中添加 logcat,我会投票打开这个问题吗?请使用以下日志编辑标题和内容。我想问题来自模型中的 SetText gettext。我们可能也需要检查一下【参考方案2】:

您在 Retrofit api 调用的响应中调用 setupRecycelerView,问题是在响应到来之前,RecyclerView 本身没有附加适配器或 layoutManager,因此出现错误。

相反,您可以在onCreate 本身内部调用setupRecycelerView,然后创建Users 列表的全局对象。像这样的:

private final ArrayList&lt;Users&gt; users = new ArrayList();

此列表将为空,适配器将使用相同的空列表初始化,然后当您从改造 api 获得响应时,使用:

users.addAll(response.getBody());

这将填充内容,然后调用adapter.notifyDataSetChanged(); 以使适配器反映更新的内容。

【讨论】:

【参考方案3】:

发生这种情况是因为您在/如果来自服务器的响应成功时初始化 RecyclerView。

onCreate() 中初始化它(调用 setupRecycelerView() )。并将adapter=new RecycelerAdapter(this,users);更改为adapter=new RecycelerAdapter(this);

让你的 RecyclerAdapter 的构造函数只接受一个参数(可能是上下文) 在您的适配器中,创建一个设置用户的公共方法。

public setUserData(ArrayList<User> users) 
    this.values = users;
    notifyDataSetChanged();

Retrofit 的调用RecycelerAdapter.setUserData(users); 响应成功。

【讨论】:

我每四个答案做一次,但我的问题还没有解决! recyclerView.setAdapter(adapter); 移动到 setupRecycelerView() 方法的底部【参考方案4】:

只需在您的setupRecycelerView() 中的setLayoutManager() 之后调用setAdapter()

【讨论】:

以上是关于RecyclerView:没有附加适配器;使用改造跳过应用程序中的布局[重复]的主要内容,如果未能解决你的问题,请参考以下文章

Fragment,RecyclerView:没有附加适配器;跳过布局

Firebase:Recyclerview 没有附加适配器,跳过布局

Firebase:Recyclerview 没有附加适配器,跳过布局

RecyclerView 没有附加适配器;跳过布局,数据不显示

recyclerView 没有适配器附加,跳过布局

RecyclerView:没有附加适配器;跳过布局[重复]