【问题标题】:onCreateView wait queries resultonCreateView 等待查询结果
【发布时间】:2018-01-17 22:26:14
【问题描述】:

我需要对我的数据库执行查询以获取一些 ID,然后使用这些 ID 对 Realm DB 执行另一个查询并将结果返回给用于创建 UI 的适配器。我的问题是适配器是在 onCreatView (主线程)中创建的,我需要让等待查询结果。你知道我该怎么做吗?真的谢谢:)

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

    Realm realm = Realm.getDefaultInstance();
    cardList = new ArrayList(realm.where(Card.class).findAll().sort("rarity"));
    View rootView = inflater.inflate(R.layout.inventory_fragment_layout, null);
    RecyclerView recyclerView = rootView.findViewById(R.id.inventory_recycler);
    recyclerView.setLayoutManager(new GridLayoutManager(this.getContext(), 2));
    adapter = new inventoryFragmentRecyclerAdapter(this.getContext(), getCards()); <----- getCards() is used here.
    adapter.setClickListener(this);
    recyclerView.setAdapter(adapter);
    TextView topText = rootView.findViewById(R.id.inv_topText);
    topText.setTypeface(Typeface.createFromAsset(getActivity().getAssets(), "fonts/Square.ttf"));

    return rootView;
}



.
.
.
.
.
.



public List<Card> getCards() { //It is used when adapter is created, and it need to contain all cards to display

    //Realm realm = Realm.getDefaultInstance();

    String urlToGet = "myurl";
    String user_name = settings.getString("username", null);

    OkHttpClient client = new OkHttpClient();

    RequestBody formBody = new FormBody.Builder()
            .add("user_name", user_name)
            .build();

    Request request = new Request.Builder()
            .url(urlToGet)
            .post(formBody)
            .build();

    client.newCall(request).enqueue(new Callback() {
        @Override
        public void onFailure(Call call, IOException e) {
            e.printStackTrace();
        }

        @Override
        public void onResponse(Call call, final Response response) throws IOException {
            if (!response.isSuccessful()) {
                throw new IOException("Unexpected code " + response);
            }

            responseCardInInventory = response.body().string();

            handler.post(new Runnable() {
                @Override
                public void run() {

                    List<CardInInv> cardListInInv = new ArrayList<>();

                    Gson gson = new Gson();
                    CardInInventory civ = gson.fromJson(responseCardInInventory, CardInInventory.class);
                    cardListInInv = getCards(civ);

                    //HERE I NEED TO USE REALM TO EXECUTE A QUERY USING cardListInInv


                }
            });
        }
    });

    //HERE I NEED TO RETURN THE RESULT OF THE QUERY EXECUTED BEFORE
    return cardsIninv;

}

编辑 1:这是我的适配器代码

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

private List<Card> dataCard = new ArrayList<>();
private LayoutInflater mInflater;
private ItemClickListener mClickListener;


// data is passed into the constructor
public inventoryFragmentRecyclerAdapter(Context context, List<Card> data) {
    this.mInflater = LayoutInflater.from(context);
    this.dataCard = data;
}

// inflates the cell layout from xml when needed
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View view = mInflater.inflate(R.layout.inventory_rw, parent, false);
    return new ViewHolder(view);
}

// binds the data to the in each cell
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
    holder.cardImage.setImageBitmap(BitmapFactory.decodeByteArray(dataCard.get(position).getCardImage(), 0, dataCard.get(position).getCardImage().length));
}

// total number of cells
@Override
public int getItemCount() {
    return dataCard.size();
}


// stores and recycles views as they are scrolled off screen
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
    ImageView cardImage;

    //instanzio le componenti della pagina

    ViewHolder(View itemView) {
        super(itemView);

        cardImage = itemView.findViewById(R.id.inv_rw_cardimage);
        itemView.setOnClickListener(this);

    }

    @Override
    public void onClick(View view) {
        if (mClickListener != null) mClickListener.onItemClick(view, getAdapterPosition());
    }
}

// convenience method for getting data at click position
Card getItem(int id) {
    return dataCard.get(id);
}

// allows clicks events to be caught
public void setClickListener(ItemClickListener itemClickListener) {
    this.mClickListener = itemClickListener;
}

// parent activity will implement this method to respond to click events
public interface ItemClickListener {
    void onItemClick(View view, int position);
}
}

【问题讨论】:

    标签: android asynchronous activity-oncreateview


    【解决方案1】:

    将您的查询移动到您的适配器并使用一个空列表启动您的适配器。在构造函数的末尾进行查询调用。成功完成查询后,通知适配器它已更改,并在查询成功完成时使用新数据处理更改。因此,在这样做之后,您的适配器将看起来像这样。

    public inventoryFragmentRecyclerAdapter(Context context, List<Card> data) {
        this.mInflater = LayoutInflater.from(context);
        getCards();
    }
    
    public void getCards() { //It is used when adapter is created, and it need to contain all cards to display
    //Realm realm = Realm.getDefaultInstance();
    
    String urlToGet = "myurl";
    String user_name = settings.getString("username", null);
    
    OkHttpClient client = new OkHttpClient();
    
    RequestBody formBody = new FormBody.Builder()
            .add("user_name", user_name)
            .build();
    
    Request request = new Request.Builder()
            .url(urlToGet)
            .post(formBody)
            .build();
    
    client.newCall(request).enqueue(new Callback() {
        @Override
        public void onFailure(Call call, IOException e) {
            e.printStackTrace();
        }
    
        @Override
        public void onResponse(Call call, final Response response) throws IOException {
            if (!response.isSuccessful()) {
                throw new IOException("Unexpected code " + response);
            }
    
            responseCardInInventory = response.body().string();
    
            handler.post(new Runnable() {
                @Override
                public void run() {
    
                    List<CardInInv> cardListInInv = new ArrayList<>();
    
                    Gson gson = new Gson();
                    CardInInventory civ = gson.fromJson(responseCardInInventory, CardInInventory.class);
                    cardListInInv = getCards(civ);
    
                    //use realm to do all your card inventory stuff to get your resulting object
                    dataCard = yourObjectListAfterUsingRealm;
                    notifyDataSetChanged();
                }
            });
        }
    });
    }
    

    【讨论】:

    • 你能做一个简单的例子吗,我有点新
    • 发布你的适配器代码,我看看能不能帮你解决问题。
    • 我已经添加了。感谢您的耐心等待。
    • 我编辑了答案,并举例说明了如何将查询移动到适配器,然后在获得结果对象时通知它。
    • 这行不通。因为在获取列表之前会调用getCards(civ);is executed asynchronously.so adapter.notifyDataSetChanged()`
    【解决方案2】:

    移动此 adapter = new inventoryFragmentRecyclerAdapter(context, yourList); onResponse() 内直接传递列表,不带getCards();

    编辑:

    当你的数据准备好时初始化你的适配器。在哪里?这取决于您的需求。

    或使用空列表对其进行初始化,并在发生更改时调用adapter.notifyDataSetChanged()(从列表中添加或删除或初始化一个全新的列表)

    【讨论】:

    • 我需要执行 2 个查询,一个到数据库,一个到领域
    • 所以如果我在获取数据后使用adapter.notifyDataSetChanged(),它会用新数据刷新吗?
    • 完全正确。来自文档notifyDataSetChanged() -> 通知附加的观察者基础数据已更改,任何反映数据集的视图都应自行刷新。
    【解决方案3】:

    使用空列表创建您的适配器
    adapter = new inventoryFragmentRecyclerAdapter(this.getContext(), new ArrayList&lt;Card&gt;());

    然后在你的适配器中创建一个这样的方法

    public void updateCardList(List<Card> cardList) { this.mCards = cardList; notifyDataSetChanged(); }

    并在
    @Override public void onResponse(Call call, final Response response)

    中调用此函数

    【讨论】:

      猜你喜欢
      • 2017-10-30
      • 2019-04-02
      • 1970-01-01
      • 1970-01-01
      • 2015-10-24
      • 2019-04-19
      • 2012-10-28
      • 2014-03-03
      • 1970-01-01
      相关资源
      最近更新 更多