当前位置: 首页 > 知识库问答 >
问题:

Android recyclerview不显示任何数据

阎单鹗
2023-03-14

我使用的是一个模板,我用一个改装2请求替换了占位符数据,该请求从URL解析数据的JSON文件,并将其放入对象列表中。我遇到了一个问题,首先执行改装调用并返回items=0,然后使用值items=0进一步执行代码,在调试器中执行了许多步骤后,它返回调用并显示正确的响应(items=12),但适配器/RecycleView操作似乎已经执行,并且它们不使用延迟到达的解析数据。

主要活动。Java语言

public class MainActivity extends AppCompatActivity {
private View parent_view;
List<Task> items = new List<Task>() {...}
private RecyclerView recyclerView;
private AdapterTasks mAdapter;
private int animation_type = ItemAnimation.BOTTOM_UP;


@Override
protected void onCreate(Bundle savedInstanceState) {
    items = DataGenerator.getTasksData();
    items.addAll(DataGenerator.getTasksData());
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_list_animation);
    parent_view = findViewById(android.R.id.content);
    initComponent();

}
private void initComponent() {

    recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
    recyclerView.setLayoutManager(new LinearLayoutManager(this));
    recyclerView.setHasFixedSize(true);
    animation_type = ItemAnimation.FADE_IN;
    setAdapter();
}

private void setAdapter() {
    //set data and list adapter
    mAdapter = new AdapterTasks(this, items, animation_type);
    recyclerView.setAdapter(mAdapter);

    // on item list clicked
    mAdapter.setOnItemClickListener(new AdapterTasks.OnItemClickListener() {
        @Override
        public void onItemClick(View view, Task obj, int position) {
            //open task view
        }
    });
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.menu_list_animation, menu);
    return true;
}

改装请求

public static List<Task> getTasksData() {
    HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
    interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
    OkHttpClient client = new OkHttpClient.Builder().addInterceptor(interceptor).build();

    Gson gson = new GsonBuilder()
            .setDateFormat("yyyy-MM-dd HH:mm:ss")
            .create();

    Retrofit retrofit= new Retrofit.Builder()
            .baseUrl("http://10.0.2.2/index.php/")
            .addConverterFactory(GsonConverterFactory.create(gson))
            .client(client)
            .build();

    TasksApi taskAPI =retrofit.create(TasksApi.class);
    Call<List<Task>> call = taskAPI.getAllTasks();

    call.enqueue(new Callback<List<Task>>() {
        @Override
        public void onResponse(Call<List<Task>> call, Response<List<Task>> response) {
            items = response.body();
        }
        @Override
        public void onFailure(Call<List<Task>> call, Throwable t) {
        }
    });
    return items;
}

适配器

public class AdapterTasks extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

private List<Task> items;
private Context ctx;

private OnItemClickListener mOnItemClickListener;
private int animation_type = 0;

public interface OnItemClickListener {
    void onItemClick(View view, Task obj, int position);
}

public void setOnItemClickListener(final OnItemClickListener mItemClickListener) {
    this.mOnItemClickListener = mItemClickListener;
}

public AdapterTasks(Context context, List<Task> items, int animation_type) {
    this.items = DataGenerator.getTasksData();
    this.items.addAll(DataGenerator.getTasksData());
    ctx = context;
    this.animation_type = animation_type;
}

public class OriginalViewHolder extends RecyclerView.ViewHolder {
    public View lyt_parent;
    public TextView laikas;
    public TextView klientas;
    public TextView darbas;
    public TextView komentaras;
    public Button atlikta;


    public OriginalViewHolder(View v) {
        super(v);
        laikas = (TextView) v.findViewById(R.id.laikas);
        klientas = (TextView) v.findViewById(R.id.name);
        lyt_parent = (View) v.findViewById(R.id.lyt_parent);
        darbas = (TextView) v.findViewById(R.id.darbas);
        komentaras = (TextView) v.findViewById(R.id.komentaras);
        atlikta = (Button) v.findViewById(R.id.atlikta);

    }
}

@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    RecyclerView.ViewHolder vh;
    View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_task, parent, false);
    vh = new OriginalViewHolder(v);
    return vh;
}

// Replace the contents of a view (invoked by the layout manager)
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {
    Log.e("onBindViewHolder", "onBindViewHolder : " + position);
    if (holder instanceof OriginalViewHolder) {
        OriginalViewHolder view = (OriginalViewHolder) holder;

        Task t = items.get(position);
        view.laikas.setText((CharSequence) t.AtlikData);
        view.klientas.setText(t.KlientasID);
        view.darbas.setText(t.VeiksmoID);
        view.komentaras.setText(t.Komentaras);
        view.lyt_parent.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (mOnItemClickListener != null) {
                    mOnItemClickListener.onItemClick(view, items.get(position), position);
                }
            }
        });
        setAnimation(view.itemView, position);
    }
}

@Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
    recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
        @Override
        public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
            on_attach = false;
            super.onScrollStateChanged(recyclerView, newState);
        }
    });
    super.onAttachedToRecyclerView(recyclerView);
}

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

private int lastPosition = -1;
private boolean on_attach = true;

private void setAnimation(View view, int position) {
    if (position > lastPosition) {
        ItemAnimation.animate(view, on_attach ? position : -1, animation_type);
        lastPosition = position;
    }
}

}

共有1个答案

阳建弼
2023-03-14

您的方法是异步的,因此在您的getTaskData方法返回空列表后,onResponse中的代码将在将来运行。您需要修改程序流以适应此情况。

下面是一个示例,通过首先将RecyclerView设置为空,然后在数据到达后添加数据,您可以定义自己的自定义回调来处理该回调。

步骤1:在某处定义接口(例如在activity或Reformation request类中)

interface OnTasksRetrieved {
    void getResult(List<Task> result);
}

第2步:更改您的getTasksData方法以接受实现该接口的回调,而不是返回列表

public static void getTasksData(OnTasksRetrieved callback) {
    //...
    call.enqueue(new Callback<List<Task>>() {
        @Override
        public void onResponse(Call<List<Task>> call, Response<List<Task>> response) {
            // Call your callback once you have retrieved the data
            callback.getResult(response.body());
        }
        @Override
        public void onFailure(Call<List<Task>> call, Throwable t) {
        }
    });

    // do not return anything
}

步骤3:在onCreate中启动异步调用时,创建回调接口的实例以传递给它来处理结果

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_list_animation);
    parent_view = findViewById(android.R.id.content);
    initComponent();
    
    // start the async fetch here - it won't finish until
    // later in the future, when it will call the callback code
    // below to update the RecyclerView data
    getTasksData(
        new OnTasksRetrieved() {
            @Override
            public void getResult(List<Task> result) {
                // The code in here runs much later in the future - the adapter
                // will already have been set up, but will be empty.
                myAdapter.setItems(result); // add this method to the adapter
            }
        }
    );
}

您需要修改适配器,使其不将列表作为输入,而是有一个类似这样的setItems方法,检索数据后将调用该方法:

private List<Task> items = new ArrayList<>();

public AdapterTasks(Context context,  int animation_type) {
    ctx = context;
    this.animation_type = animation_type;
}

public void setItems(List<Task> data) {
    items.clear();
    items.addAll(data);
    notifyDataSetChanged();
}
 类似资料:
  • 我试图用自己的数据创建一个dataTable:代码如下: 但当我运行它时,我看到一张空桌子。我想查看我的数据,我怎么能?

  • 我目前正在使用Firebase_Auth.当我点击登录按钮并且Firebase连接到我的应用程序时,一切似乎都很好。它在终端上显示用户的ID。但是当我去消防基地时。 它无法识别任何已注册的用户。 Ps:问题是当用户注册时,它不会显示给firebase。

  • 问题内容: 我正在一个用于启动和运行的项目。我对docker- compose不太熟悉,我在文档中找不到真正的答案。根据文档,该命令从docker文件重建容器,但是这似乎没有发生。 当我尝试添加用于调试的命令时,没有任何反应。该程序已经抛出了一些打印命令,因此我尝试更改这些命令以确保它们始终打印相同的命令。我是否必须在命令中添加一些内容以进行容器重建? docker-compose / yml:

  • 我尝试在我的JavaFX应用程序中实现一个TreeView。但不幸的是,没有项目显示,但我找不到一个问题。我搜索了一些例子,并像他们一样做了。 这是我的控制器代码: 我的FXML代码:

  • 我有个组件叫我的组件 模型贝宝。php 控制器paypal.php 意见 贝宝视图。html。php索引。html TMPL(文件夹)default.phpindex.html 在控制器中,我有这个代码 在模型中我有一段代码 在视图/模板/default.php我有这个 当我运行这个url