RecyclerView多次显示适配器中的最后一项。需要在RecyclerView

时间:2015-08-24 21:15:43

标签: java android parse-platform nullpointerexception android-recyclerview

所以我试图将Parse数据库查询中的数据加载到recyclerView中。查询将我的所有数据完美地加载到我的ArrayList中,然后将其添加到我的适配器中。

不幸的是,我的recyclerView只显示适配器数据的最后一个添加内容。但是,如果适配器中有15个对象,则最后一次添加将在屏幕上重复15次。

我认为问题在于,由于某种原因,数据ArrayList内部的值不存在于查询之外,即使我在类中声明它。

这是我的MainActivity代码:

public class MainActivity extends  ActionBarActivity implements DataAdapter.ClickListener {
private RecyclerView recyclerView;
static DataAdapter adapter;

public TextView tvParseUser;
private Context context;
String currentUser;

Data current = new Data();

List<Data> data = new ArrayList<>();


public static String BROADCAST_ACTION =
        "broadcast_action_packagename";
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    IntentFilter filter = new IntentFilter();
    filter.addAction(BROADCAST_ACTION);
    filter.addCategory(Intent.CATEGORY_DEFAULT);
    registerReceiver(br, filter);

//testing Sree's suggestion
        adapter = new CommitmentDataAdapter(getApplicationContext(), data);
        Log.d("DATABEFOREADD", data.toString()); //data here is empty

    startService(new Intent(this, Broadcast_Service.class));
    tvParseUser = (TextView) findViewById(R.id.ParseUserName);
    setContentView(R.layout.activity_main);

    ParseQuery<ParseObject> query = ParseQuery.getQuery("ColumnTitle");
    query.whereEqualTo("author", ParseUser.getCurrentUser());
    recyclerView = (RecyclerView) findViewById(R.id.recyclerView); 
    recyclerView.setLayoutManager(new LinearLayoutManager(this));
    query.findInBackground(new FindCallback<ParseObject>() {

        @Override
        public void done(List<ParseObject> list, ParseException e) { //returns actual Parse Object
            if (e == null)
            {
                for (ParseObject getData : list)
                {

                    current.1= getData.getString("1");
                    current.2= getData.getString("2");
                    current.3= getData.getString("3");
                    current.4= getData.getString("4");
                    current.5= getData.getString("5");

                    current.combined= current.1 + current.2 + current.3 + current.4;
                    //checked Log.d, query is working fine. ArrayList should have an object of all the data for use

                    data.add(current);
                    Log.d("data", data.toString());
                    Log.d("CurrentCombined", current.combined);
                    adapter.notifyDataSetChanged(); //Sree's suggestion




                    //data correctly contains list of objects that I need

                }

                Log.d("dataInfo", String.valueOf(data));
                Log.d("Current", current.toString());
            }

            else
            {

            }

            recyclerView.setAdapter(adapter); //set recyclerView to this adapter

        }

    });
    Log.d("ADAPTERDATA", data.toString()); //NOTE THIS RETURNS AN EMPTY ARRAY. WHY?!
}

public BroadcastReceiver br = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        updateGUI(intent);
        adapter.notifyDataSetChanged();

    }
};

DataAdapter代码:

    package com.example.android.moneyspeaks;

import android.app.AlarmManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.CountDownTimer;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.Chronometer;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import org.slf4j.helpers.Util;
import org.w3c.dom.Text;

import java.sql.Time;
import java.util.Calendar;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit;


public class DataAdapter extends RecyclerView.Adapter<DataAdapter.MyViewHolder> {
    List<Data> data = Collections.emptyList();
    private LayoutInflater inflater;
    private Context context;
    private ClickListener clickListener;
    long millisCountDownTime;
    Intent intent;
    PendingIntent pendingIntent;
    Thread thread;
    Handler handler;
    Long now;
    Long later;
    Integer i = 0;
    final Handler myHandler = new Handler();

    public DataAdapter(Context context, List<Data> data) 
    {
        inflater = LayoutInflater.from(context);
        this.data = data;
    }

    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
    {
        View view = inflater.inflate(R.layout.recycler_view_layout, parent, false); 
        MyViewHolder holder = new MyViewHolder(view); 

        return holder;
    }

    public void setClickListener(ClickListener clickListener) {
        this.clickListener = clickListener;

    }

    @Override
    public void onBindViewHolder(final MyViewHolder holder, int position) {
        Data current = data.get(position);
        holder.combined.setText(current.combined);
        holder.codeTimer.setText(current.goalTimer);
        holder.submitCode.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(v.getContext(), "HELL YA", Toast.LENGTH_LONG).show();

            }
        });

        if (current.classify2.equals("day(s)")) {
            millisCountDownTime = 86400000;
        } else if (current.classify2.equals("week(s)")) {
            millisCountDownTime = 604800000;
        } else if (current.classify2.equals("hour(s)")) {
            millisCountDownTime = 3600000;
        } else if (current.classify2.equals("minute(s)")) {
            millisCountDownTime = 6000;
        }
        final Runnable myRunnable = new Runnable() {
            @Override
            public void run() {
                holder.codeTimer.setText(String.valueOf(i));

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

class MyViewHolder extends RecyclerView.ViewHolder {
    TextView combined;
    TextView enterCode;
    TextView codeTimer;
    EditText codeInputField;
    Button submitCode;

    public MyViewHolder(View itemView) {
        super(itemView);
        combined= (TextView) itemView.findViewById(R.id.combinedSentence);
        codeTimer = (TextView) itemView.findViewById(R.id.codeTimer);
        submitCode = (Button) itemView.findViewById(R.id.submitTheCode);

        itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (v.getId() == R.id.submitTheCode) {
                    Intent i = new Intent(v.getContext(), Different.class);
                    v.getContext().startActivity(i);

                }

            }
        });
    }
}

public interface ClickListener {
    public void itemClicked(View view, int position);
}
}

3 个答案:

答案 0 :(得分:2)

我也面临同样的问题,并打破了我的头谷歌搜索.. 绝对解决方案是在主要活动的for循环中创建current类型Data对象

说明:当您在循环外声明current对象时,您正在创建单个对象并使用具有相同值的相同对象

快乐的编码!!

答案 1 :(得分:0)

我认为是因为你在初始化适配器之前调用了adapter.notifyDataSetChanged()。因为它只是在回调上初始化,我认为你可能有可能在回调完成之前调用notifyDataSetChanged()(我想你提到广播每秒都会发生)。我无法100%确定,因为我无法看到您的其余代码。

答案 2 :(得分:0)

所以,让我直截了当。您在onCreate()中执行以下操作:

  1. 做一些设置
  2. 创建适配器。
  3. 启动一个在另一个线程中运行以填充数据的进程。
  4. 几乎立即尝试使用该数据记录消息。
  5. 因此,您希望在执行3中的代码和基本上下一组4中的代码指令之间,Android将在另一个CPU上安排该进程,运行完成,将该数据编组到由UI线程,所有的及时,以便当它执行4的代码时,有实际的数据?你有一个特殊的手机,其中UI线程运行在一个速度慢100倍的核心?

    没有。线程同步问题没有灵丹妙药。要么重新设计代码,以便跨线程访问数据正确同步,要么使用强制执行所需行为的线程同步原语。