私はRecyclerViewに無限のデータロードを実装しています。最後のアイテムが表示されることをソフトウェアが検出すると、新しいアイテムをダウンロードしてloadMoreData()
関数を呼び出しますが、新しいデータセットは表示されません。
notifyDataSetChanged()
を呼び出したとき、何も起こらない。
ビューを更新する解決策は1つしかありませんが、アダプタを再設定することですが、問題はrecyclerviewが最初の位置に戻り、recyclerviewが最初の位置から最後の位置までスクロールアップすることです。
RecyclerViewActivity.Java
_ RecyclerView rv;
DatabaseHelpr databaseHelpr;
RVAdapter adapter;
LocationFinder locationfinder;
Location currentLocation;
ArrayList<ServiceModel> childList, list;
private int MainService_ID, city_id;
String url2;
ActionBar actionBar;
JSONArray items = null;
Utility utility;
Double lat, longi;
LinearLayoutManager llm;
int counter=0;
ProgressBar progressBar;
private static final String TAG_ITEMS = "items";
private static final String TAG_LOCALITY = "Locality";
private static final String TAG_BUSINESS_ID = "Business_Id";
private static final String TAG_LONGITUDE = "Longitude";
private static final String TAG_BUSINESS_NAME = "Business_Name";
private static final String TAG_LATITUDE = "Latitude";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.recyclerview_activity);
list = new ArrayList<>();
utility = new Utility(this);
llm = new LinearLayoutManager(this);
Bundle bundle=getIntent().getExtras();
MainService_ID=bundle.getInt("service_id");
String mainService_Name = bundle.getString("service_name");
city_id = bundle.getInt("city_id");
lat= bundle.getDouble("lat");
longi=bundle.getDouble("longi");
rv=(RecyclerView)findViewById(R.id.rv);
rv.setLayoutManager(llm);
actionBar = getSupportActionBar();
assert actionBar != null;
actionBar.setDisplayHomeAsUpEnabled(true);
actionBar.setTitle(mainService_Name);
//Here city_id = 8, lat = 18.552954, longi = 73.897200, counter=0, MainService_ID = 5
String url="https://servicedata2-dot-indiacomapi.appspot.com/_ah/api/servicedata/v1/ServiceData?city_id=";
url2 =url+city_id+"&lat="+lat+"&lng="+longi+"&roll="+counter+"&service_id="+MainService_ID;
AsyncHttpClient client = new AsyncHttpClient();
progressBar=(ProgressBar) findViewById(R.id.progressBar1);
progressBar.setVisibility(View.VISIBLE);
client.get(url2, new AsyncHttpResponseHandler() {
@Override
public void onSuccess(int statusCode, Header[] headers, byte[] response) {
// called when response HTTP status is "200 OK"
String s = new String(response);
try {
JSONObject jsonObj = new JSONObject(s);
// Getting JSON Array node
items = jsonObj.getJSONArray(TAG_ITEMS);
// looping through All Contacts
for (int i = 0; i < items.length(); i++) {
JSONObject c = items.getJSONObject(i);
String locality = c.getString(TAG_LOCALITY);
String business_Id = c.getString(TAG_BUSINESS_ID);
String longitude = c.getString(TAG_LONGITUDE);
String latitude = c.getString(TAG_LATITUDE);
String business_Name = c.getString(TAG_BUSINESS_NAME);
locationfinder = new LocationFinder(RecyclerViewActivity.this);
// check if GPS enabled
if (locationfinder.canGetLocation()) {
double lat = locationfinder.getLatitude();
double longi = locationfinder.getLongitude();
currentLocation = new Location("");
currentLocation.setLatitude(lat);
currentLocation.setLongitude(longi);
} else {
locationfinder.showSettingsAlert();
}
Location savedLocation = new Location("databaseLocation");
savedLocation.setLatitude(Double.parseDouble(latitude));
savedLocation.setLongitude(Double.parseDouble(longitude));
Double difference = currentLocation.distanceTo(savedLocation) * (0.001);
difference = Double.parseDouble(new DecimalFormat("##.##").format(difference));
String newDifference = String.valueOf(difference) + " km";
ServiceModel serviceModel = new ServiceModel(business_Id, business_Name, newDifference, locality);
list.add(serviceModel);
}
} catch (JSONException e) {
e.printStackTrace();
}
progressBar.setVisibility(View.GONE);
adapter = new RVAdapter(RecyclerViewActivity.this, list);
rv.setAdapter(adapter);
rv.addOnScrollListener(new EndlessRecyclerOnScrollListener(llm) {
@Override
public void onLoadMore(int current_page) {
// counter= counter+1;
loadMoreData();
}
});
}
@Override
public void onFailure(int statusCode, Header[] headers, byte[] errorResponse, Throwable e) {
// called when response HTTP status is "4XX" (eg. 401, 403, 404)
//Toast.makeText(getApplicationContext(),""+statusCode,Toast.LENGTH_LONG).show();
}
});
}
private void loadMoreData() {
counter= counter+1;
//Here city_id = 8, lat = 18.552954, longi = 73.897200, counter=1, MainService_ID = 5
String url="https://servicedata2-dot-indiacomapi.appspot.com/_ah/api/servicedata/v1/ServiceData?city_id=";
url2 =url+city_id+"&lat="+lat+"&lng="+longi+"&roll="+counter+"&service_id="+MainService_ID;
AsyncHttpClient client = new AsyncHttpClient();
progressBar=(ProgressBar) findViewById(R.id.progressBar1);
progressBar.setVisibility(View.VISIBLE);
client.get(url2, new AsyncHttpResponseHandler() {
@Override
public void onSuccess(int statusCode, Header[] headers, byte[] response) {
// called when response HTTP status is "200 OK"
String s = new String(response);
try {
JSONObject jsonObj = new JSONObject(s);
// Getting JSON Array node
items = jsonObj.getJSONArray(TAG_ITEMS);
// looping through All Contacts
for (int i = 0; i < items.length(); i++) {
JSONObject c = items.getJSONObject(i);
String locality = c.getString(TAG_LOCALITY);
String business_Id = c.getString(TAG_BUSINESS_ID);
String longitude = c.getString(TAG_LONGITUDE);
String latitude = c.getString(TAG_LATITUDE);
String business_Name = c.getString(TAG_BUSINESS_NAME);
locationfinder = new LocationFinder(RecyclerViewActivity.this);
// check if GPS enabled
if (locationfinder.canGetLocation()) {
double lat = locationfinder.getLatitude();
double longi = locationfinder.getLongitude();
currentLocation = new Location("");
currentLocation.setLatitude(lat);
currentLocation.setLongitude(longi);
} else {
locationfinder.showSettingsAlert();
}
Location savedLocation = new Location("databaseLocation");
savedLocation.setLatitude(Double.parseDouble(latitude));
savedLocation.setLongitude(Double.parseDouble(longitude));
Double difference = currentLocation.distanceTo(savedLocation) * (0.001);
difference = Double.parseDouble(new DecimalFormat("##.##").format(difference));
String newDifference = String.valueOf(difference) + " km";
ServiceModel serviceModel = new ServiceModel(business_Id, business_Name, newDifference, locality);
list.add(serviceModel);
}
} catch (JSONException e) {
e.printStackTrace();
}
progressBar.setVisibility(View.GONE);
//adapter = new RVAdapter(RecyclerViewActivity.this, list);
//rv.setAdapter(adapter);
adapter.notifyDataSetChanged();
}
@Override
public void onFailure(int statusCode, Header[] headers, byte[] errorResponse, Throwable e) {
}
});
Toast.makeText(this, "Net is present", Toast.LENGTH_SHORT).show();
}
}
_
RVAdapter.Java
_public class RVAdapter extends RecyclerView.Adapter<RVAdapter.PersonViewHolder>{
private final LayoutInflater mInflater;
List<ServiceModel> persons ;
private Context mContext;
public RVAdapter(Context context,List<ServiceModel> persons){
this.mInflater = LayoutInflater.from(context);
this.persons = new ArrayList<>(persons);
this.mContext = context;
}
@Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
}
@Override
public PersonViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item, viewGroup, false);
PersonViewHolder pvh = new PersonViewHolder(v);
return pvh;
}
@Override
public void onBindViewHolder(PersonViewHolder personViewHolder, int i) {
ServiceModel person = persons.get(i);
personViewHolder.businessName.setOnClickListener(clickListener);
personViewHolder.image_url.setOnClickListener(clickListenerImage);
personViewHolder.businessName.setTag(personViewHolder);
personViewHolder.difference.setTag(personViewHolder);
personViewHolder.business_id.setTag(personViewHolder);
personViewHolder.image_url.setTag(personViewHolder);
personViewHolder.locality.setTag(personViewHolder);
personViewHolder.businessName.setText(Html.fromHtml(person.getBusinessname()));
String firstLetter = String.valueOf(person.getBusinessname().charAt(0));
ColorGenerators generator = ColorGenerators.MATERIAL; // or use DEFAULT
int color = generator.getColor(person.getBusinessname());
TextDrawable drawable = TextDrawable.builder().buildRound(firstLetter, color); // radius in px
personViewHolder.image_url.setImageDrawable(drawable);
personViewHolder.difference.setText(Html.fromHtml(person.getNewDiffer()));
personViewHolder.locality.setText(Html.fromHtml(person.getLocality()));
personViewHolder.bind(person);
}
View.OnClickListener clickListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
PersonViewHolder holder = (PersonViewHolder) view.getTag();
int position = holder.getPosition();
ServiceModel person = persons.get(position);
String businessids = person.getBusinessid();
Intent intent = new Intent(mContext, BusinessInfoActivity.class);
intent.putExtra("businessids", businessids);
mContext.startActivity(intent);
}
};
View.OnClickListener clickListenerImage = new View.OnClickListener() {
@Override
public void onClick(View view) {
PersonViewHolder holder = (PersonViewHolder) view.getTag();
int position = holder.getPosition();
ServiceModel person = persons.get(position);
String businessids = person.getBusinessid();
Intent intent = new Intent(mContext, BusinessInfoActivity.class);
intent.putExtra("businessids", businessids);
mContext.startActivity(intent);
}
};
@Override
public int getItemCount() {
return persons.size();
}
public void animateTo(List<ServiceModel> models) {
applyAndAnimateRemovals(models);
applyAndAnimateAdditions(models);
applyAndAnimateMovedItems(models);
}
private void applyAndAnimateRemovals(List<ServiceModel> newModels) {
for (int i = persons.size() - 1; i >= 0; i--) {
final ServiceModel model = persons.get(i);
if (!newModels.contains(model)) {
removeItem(i);
}
}
}
private void applyAndAnimateAdditions(List<ServiceModel> newModels) {
for (int i = 0, count = newModels.size(); i < count; i++) {
final ServiceModel model = newModels.get(i);
if (!persons.contains(model)) {
addItem(i, model);
}
}
}
private void applyAndAnimateMovedItems(List<ServiceModel> newModels) {
for (int toPosition = newModels.size() - 1; toPosition >= 0; toPosition--) {
final ServiceModel model = newModels.get(toPosition);
final int fromPosition = persons.indexOf(model);
if (fromPosition >= 0 && fromPosition != toPosition) {
moveItem(fromPosition, toPosition);
}
}
}
public ServiceModel removeItem(int position) {
final ServiceModel model = persons.remove(position);
notifyItemRemoved(position);
return model;
}
public void addItem(int position, ServiceModel model) {
persons.add(position, model);
notifyItemInserted(position);
}
public void moveItem(int fromPosition, int toPosition) {
final ServiceModel model = persons.remove(fromPosition);
persons.add(toPosition, model);
notifyItemMoved(fromPosition, toPosition);
}
public static class PersonViewHolder extends RecyclerView.ViewHolder {
protected CardView cv;
protected TextView businessName, difference, business_id, locality;
protected ImageView image_url;
public PersonViewHolder(View itemView) {
super(itemView);
cv = (CardView)itemView.findViewById(R.id.cv);
businessName = (TextView)itemView.findViewById(R.id.business_name);
difference = (TextView)itemView.findViewById(R.id.txtDifferenece);
business_id = (TextView)itemView.findViewById(R.id.business_id);
image_url = (ImageView)itemView.findViewById(R.id.thumbnail);
locality= (TextView)itemView.findViewById(R.id.txtLocality);
}
public void bind(ServiceModel model) {
businessName.setText(model.getBusinessname());
}
}
}
_
notifyDataSetChanged()
をアダプターに設定する方法を教えてください。私のコードでは機能していません。私はすでにstackoverflowに投稿されているすべての回答をチェックしました。
新しいリストをRecyclerViewアダプターに設定している場合、アダプターにリストを設定します。
アダプタでメソッドsetItems(list)
を作成し、notifyDataSetChanged()
の前に呼び出し、アダプタでそれを行います
_this.persons = new ArrayList<>(persons);
_
setItems
このメソッドをアダプターに追加します。
_public void setItems(List<ServiceModel> persons) {
this.persons = persons;
}
_
次のようにnotifyDataSetChanged()
の前に呼び出します:
_adapter.setItems(list);
adapter.notifyDataSetChanged();
_
問題はこれらの行にあります。
_ adapter = new RVAdapter(RecyclerViewActivity.this, list);
rv.setAdapter(adapter);
adapter.notifyDataSetChanged();
_
毎回アダプターを初期化しています。再初期化する必要はありません。 arraylist
を更新するだけで、adapter.notifyDataSetChanged();
を呼び出すと動作します。
前述の@Beenaのように、成功応答では常に新しいアダプターを作成および設定しています。
1つの方法は、アダプターを作成して初めてリサイクラビューに設定し、APIコールバックのonSuceess()でアダプターのメソッドを呼び出すことです。
これらのアダプターメソッドでは、メインの配列リストにその新しいデータを追加し、notifyDataSetChangedではなくnotifyItemInserted()を実行します。この方法で、recyclerViewのデフォルトの追加アニメーションも表示されます。
NotifyDataSetChanged()を呼び出すRVAdapterのメソッドを追加して、これを解決しました。
単にRVAdapterで:
public void refreshList(){
notifyDataSetChanged();
}
必要なときにMainActivityでこのメソッドを呼び出します。
rVAdapter.refreshList();
リストをすべて埋めると、以下のメソッドが呼び出されます。
if (adapter != null) // it works second time and later
adapter.notifyDataSetChanged();
else { // it works first time
adapter = new AdapterClass(context,list);
listView.setAdapter(adapter);
}