将视图保留在最后一项 - LoadMore RecyclerView
Posted
技术标签:
【中文标题】将视图保留在最后一项 - LoadMore RecyclerView【英文标题】:keep the view in the last item - LoadMore RecyclerView 【发布时间】:2018-12-07 06:36:45 【问题描述】:晕,我的应用中有 LoadMore RecyclerView。这是工作,但是当我加载更多项目时,recyclerview 总是保持显示列表的顶部。我的意思是,它应该显示最后加载的项目。
任何人,你愿意帮助我吗?谢谢。
我的屏幕截图:
-
1 - 5 is the first list loaded:
-
6 - 10 shown after scrolling the recyclerView, but after 6 - 10
loaded, recyclerView always keep showing the top of the list (1-5)
:
这是我的代码:
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_job_company);
//intent untuk nerima value namaAdver dan handling jika tdk ada list
TextView namaCompany = (TextView) findViewById(R.id.tv_companyname);
TextView emptyList = (TextView) findViewById(R.id.emptylist);
loading = (ProgressBar) findViewById(R.id.loading);
loading.getIndeterminateDrawable().setColorFilter(getResources().getColor(R.color.colorPrimary), PorterDuff.Mode.MULTIPLY);
Intent intentGet = getIntent();
companyName = intentGet.getStringExtra("namaCompany");
idComp = intentGet.getStringExtra("idCompany");
try
compID = Integer.parseInt(idComp);
catch (NumberFormatException nfe)
namaCompany.setText(companyName);
setTitle(intentGet.getStringExtra("namaCompany"));
PaginationJobCompany(compID, pageNum);
recyclerView = (RecyclerView) findViewById(R.id.rv_job_company2);
recyclerView.setHasFixedSize(true);
mLayoutManager = new LinearLayoutManager(getApplicationContext());
recyclerView.setLayoutManager(mLayoutManager);
recyclerView.addItemDecoration(new DividerItemDecoration(getApplicationContext(), null)); //untuk divider
private void PaginationJobCompany(final int compID, final int pageNumber)
try
loading.getIndeterminateDrawable().setColorFilter(getResources().getColor(R.color.colorPrimary), PorterDuff.Mode.MULTIPLY);
loading.setVisibility(View.GONE);
//authorization JWT pref_token berdasarkan string yg disimpan di preferenceManager pada class login.
Authorization = (PreferenceManager.getDefaultSharedPreferences(getApplicationContext()).getString(
getResources().getString(R.string.pref_token), ""));
//production
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(getResources().getString(R.string.base_url))
.addConverterFactory(GsonConverterFactory.create())
.build();
//assign variabel request ke class interface TabAdverRequest
final APIInterfaces request = retrofit.create(APIInterfaces.class);
Call<ReportJobModel> call = request.getReportPagination(compID, pageNum, length, Authorization); //ngirim ke API
call.enqueue(new Callback<ReportJobModel>()
@Override
public void onResponse(Call<ReportJobModel> call, Response<ReportJobModel> response)
loading.getIndeterminateDrawable().setColorFilter(getResources().getColor(R.color.colorPrimary), PorterDuff.Mode.MULTIPLY);
loading.setVisibility(View.GONE);
if (response.isSuccessful())
companyResult = response.body().getResult();
if (!companyResult.isEmpty())
company.addAll(companyResult);
for (int i = 0; i < companyResult.size(); i++)
if (company.get(i).getCompanyID() == compID)
jobItemResult = response.body().getResult().get(i).getJobs();
jobItem.addAll(jobItemResult);
else
for (int j = 0; j < companyResult.size(); j++)
if (company.get(j).getCompanyID() == compID)
lastId = jobItem.size()-1;
adapter = new JobCompanyAdapter(jobItem, recyclerView);
recyclerView.setAdapter(adapter);
adapter.setOnLoadMoreListener(new OnLoadMoreListener()
@Override
public void onLoadMore()
//add null , so the adapter will check view_type and show progress bar at bottom
jobItem.add(null);
adapter.notifyItemInserted(jobItem.size() - 1);
loading.getIndeterminateDrawable().setColorFilter(getResources().getColor(R.color.colorPrimary), PorterDuff.Mode.MULTIPLY);
loading.setVisibility(View.GONE);
handler.postDelayed(new Runnable()
@Override
public void run()
jobItem.remove(jobItem.size() - 1);
adapter.notifyItemRemoved(jobItem.size());
loading.setVisibility(View.GONE);
pageNum++;
loading.setVisibility(View.GONE);
PaginationJobCompany(compID, pageNum);
adapter.notifyDataSetChanged();
, 2000);
);
else if (response.errorBody() != null)
loading.setVisibility(View.GONE);
Toast.makeText(getApplicationContext(), "Gagal Memuat. Periksa Koneksi Anda!", Toast.LENGTH_LONG).show();
else if (response.code() == 400)
loading.setVisibility(View.GONE);
Toast.makeText(getApplicationContext(), "Gagal Memuat. Periksa Koneksi Anda!", Toast.LENGTH_LONG).show();
else
loading.setVisibility(View.GONE);
Toast.makeText(getApplicationContext(), "Gagal Memuat. Periksa Koneksi Anda! 1", Toast.LENGTH_LONG).show();
@Override
public void onFailure(Call<ReportJobModel> call, Throwable t)
Toast.makeText(getApplicationContext(), "Gagal Memuat. Periksa Koneksi Anda! 1", Toast.LENGTH_LONG).show();
);
catch (Exception e)
Toast.makeText(getApplicationContext(), "Gagal Memuat. Periksa Koneksi Anda! 1", Toast.LENGTH_LONG).show();
【问题讨论】:
那我该怎么办?你愿意帮助我吗@HawkPriest 【参考方案1】:好的,我假设您已经为RecyclerView
实现了EndlessScrollListener
,如果没有,我强烈建议您检查一下:https://gist.github.com/nesquena/d09dc68ff07e845cc622。为了进一步使您的代码更具可读性和适应性,我建议您使用更多的封装。
例如:有一个 NetworkHandler
为您回调 UI。相应地切换 UI 行为的位置。为此,您需要一个OnDataCallback
接口。
// OnDataCallback.java
interface OnDataCallback<T>
void onData(T data);
void onError(Throwable error);
// NetworkHandler.java
public class NetworkHandler<T>
@Nullable
protected OnDataCallback<T> dataCallback;
protected int pageIndex = 0;
public void setDataCallback(OnDataCallback<T> dataCallback)
this.dataCallback = dataCallback;
public void removeDataCallback()
dataCallback = null;
public void setPageIndex(int pageIndex)
this.pageIndex = pageIndex;
public void updatePageNumber()
pageIndex++;
创建一个RetrofitUtils
类作为可用于创建服务的单例。
public static class RetrofitUtils
private static RetrofitUtils utils;
public static RetrofitUtils getInstance()
if (utils == null)
utils = new RetrofitUtils();
return utils;
private Retrofit retrofit;
public Retrofit getRetrofitInstance()
if (retrofit == null)
retrofit = new Retrofit.Builder()
.baseUrl("http://mybaseurl.api/v1/")
.addConverterFactory(GsonConverterFactory.create())
.build();
return retrofit;
public JobService constructJobService(Class<JobService> uClass)
return getRetrofitInstance().create(uClass);
public LoginService construcstLoginService(Class<LoginService> uClass)
return getRetrofitInstance().create(uClass);
然后继承 NetworkHandler
并根据您的规范覆盖方法,例如有一个 JobNetworkHandler
为您执行请求和分页。创建自定义 Throwable
类以更有效地处理错误,就像示例中的 ErrorBodyThrowable
一样。剩下的就是你必须实现回调并在片段或活动中设置 UI。
public class JobReportHandler extends NetworkHandler<ReportJobModel>
int compID;
int length;
Authorization auth = AuthUtils.getAuth();
@Override
public void updatePageNumber()
super.updatePageNumber();
fetchJobsModel(compID, length);
public void fetchJobsModel(int compID, int length)
this.compID = compID;
this.length = length;
JobService request = RetrofitUtils.getInstance().constructJobService(JobService.class);
Call<ReportJobModel> call = request.getReportPagination(compID, pageIndex, length, auth); //ngirim ke API
call.enqueue(new Callback<JobModel>()
@Override
public void onResponse(Call<JobModel> call, Response<JobModel> response)
// manipulate data and pass the UI model
// that needs to be handled by the view
ReportJobModel reportJobModel = response.convertToReport();
if (dataCallback == null) return;
if (response.isSuccessful())
dataCallback.onData(reportJobModel);
else if (response.errorBody() != null)
dataCallback.onError(new ErrorBodyThrowable());
else if (response.code() == 400)
dataCallback.onError(new ApiError());
else
// do something else
@Override
public void onFailure(Call<ReportJobModel> call, Throwable t)
if (dataCallback != null)
dataCallback.onError(t);
);
public class ErrorBodyThrowable extends Throwable
ErrorBodyThrowable()
super("Gagal Memuat. Periksa Koneksi Anda!");
请注意,更新 pageIndex 会自动触发网络调用,因此您可以避免编写冗余调用。
最后在你的Fragment
或Activity
有这样的东西:
// TestFragment.java
public final class TestFragment extends Fragment implements OnDataCallback<ReportJobModel>, CustomRecyclerOnScrollListener
@Bind(R.id.myRecyclerView)
RecyclerView myRecyclerView;
private JobsAdapter adapter;
private final JobReportHandler jobHandler = new JobReportHandler();
private final Handler mainThreadHandler = new Handler(Looper.getMainLooper());
private MyCustomEndlessScrollListener endlessScroll;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState)
return inflater.inflate(R.layout.my_list_fragment, container, false);
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState)
super.onViewCreated(view, savedInstanceState);
endlessScroll = = new MyCustomEndlessScrollListener(this);
setUi();
initializeNetwork();
private void initializeNetwork()
// after setting the UI Parameters
jobHandler.setDataCallback(this);
jobHandler.fetchJobsModel(compID, length);
@Override
public void onData(ReportJobModel dataModel)
// just a safety mechanism to handle threading
// use the main thread dispatcher
mainThreadHandler.post(new Runnable()
@Override
public void run()
final ArrayList<JobItem> data = dataModel.getJobItems();
UiUtils.makeGone(loadingProgress);
if (myRecyclerView.getAdapter() == null || jobAdapter == null)
jobAdapter = JobsAdapter(data);
myRecyclerView.setAdapter(jobAdapter);
myRecyclerView.setOnScrollChangeListener(endlessScroll);
else
jobAdapter.getItems().addAll(data);
jobAdapter.notifyItemRangeInserted(jobAdapter.getItems().size() -1, data.size());
);
@Override
public void onScrolledToBottom()
jobHandler.updatePageNumber();
@Override
public void onError(final Throwable error)
// just a safety mechanism to handle threading
// use the main thread dispatcher
mainThreadHandler.post(new Runnable()
@Override
public void run()
if (error.getMessage() != null && !error.getMessage().isEmpty())
Toast.makeText(getContext(), error.getMessage(), Toast.LENGTH_LONG).show();
);
@Override
public void onDestroy()
jobHandler.removeDataCallback();
super.onDestroy();
如您所见,onScrolledToBottom()
将通过CustomRecyclerScrollListener
触发,然后触发updatePageNumber()
,然后调用fetchJobModel()
,最终您将在片段上收到回调。
【讨论】:
谢谢你的帮助,我会试试@HawkPriest以上是关于将视图保留在最后一项 - LoadMore RecyclerView的主要内容,如果未能解决你的问题,请参考以下文章
如何在 xamarin 表单的集合视图中的最后一项旁边添加图像/按钮?