我有一个搜索查询的活动(使用async
任务和服务器端PHP
)并在recycler view
中列出一个列表,现在我想实现无穷无尽/无限滚动当用户到达底部时。我试图使用EndlessScrollListener
来做到这一点。我需要帮助有两个问题。
首先,新列表重新创建自己,而不是附加到旧列表。
第二,current_page
int变量保持其前一次搜索的值并滚动,意味着第二次运行AsyncTask
时,current_page
int变量仍然保留第一次的值时间并没有重置。
public class MainActivity extends AppCompatActivity {
// CONNECTION_TIMEOUT and READ_TIMEOUT are in milliseconds
public static final int CONNECTION_TIMEOUT = 10000;
public static final int READ_TIMEOUT = 15000;
private RecyclerView mRVFish;
private AdapterFish mAdapter;
private LinearLayoutManager mLayoutManager;
private String searchQuery;
SearchView searchView = null;
private String query;
private EndlessRecyclerOnScrollListener mScrollListener = null;
private SwipeRefreshLayout mSwipeRefreshLayout = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mRVFish = (RecyclerView) findViewById(R.id.fishPriceList);
mLayoutManager = new LinearLayoutManager(MainActivity.this);
mRVFish.setLayoutManager(mLayoutManager);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// adds item to action bar
getMenuInflater().inflate(R.menu.search_main, menu);
// Get Search item from action bar and Get Search service
MenuItem searchItem = menu.findItem(R.id.action_search);
SearchManager searchManager = (SearchManager) MainActivity.this.getSystemService(Context.SEARCH_SERVICE);
if (searchItem != null) {
searchView = (SearchView) searchItem.getActionView();
}
if (searchView != null) {
searchView.setSearchableInfo(searchManager.getSearchableInfo(MainActivity.this.getComponentName()));
searchView.setIconified(false);
}
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
return super.onOptionsItemSelected(item);
}
// Every time when you press search button on keypad an Activity is recreated which in turn calls this function
@Override
protected void onNewIntent(Intent intent) {
// Get search query and create object of class AsyncFetch
if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
query = intent.getStringExtra(SearchManager.QUERY);
if (searchView != null) {
searchView.clearFocus();
}
int startrow =0;
String type="";
String filetype="";
AsyncFetch myTask = new AsyncFetch(query, startrow, type, filetype);
myTask.execute();
mScrollListener = new EndlessRecyclerOnScrollListener(mLayoutManager) {
@Override
public void onLoadMore(int current_page) {
int startrow=current_page;
String type="";
String filetype="";
AsyncFetch myTask = new AsyncFetch(query, startrow, type, filetype);
myTask.execute();
}
};
mRVFish.addOnScrollListener(mScrollListener);
// enable pull down to refresh
mSwipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipeRefreshLayout);
mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
int startrow =0;
String type="";
String filetype="";
AsyncFetch myTask = new AsyncFetch(query, startrow, type, filetype);
myTask.execute();
// after refresh is done, remember to call the following code
if (mSwipeRefreshLayout != null && mSwipeRefreshLayout.isRefreshing()) {
mSwipeRefreshLayout.setRefreshing(false); // This hides the spinner
}
}
});
}
}
// Create class AsyncFetch
private class AsyncFetch extends AsyncTask<String, String, String> {
ProgressDialog pdLoading = new ProgressDialog(MainActivity.this);
HttpURLConnection conn;
URL url = null;
String searchQuery;
int startrow;
String type;
String filetype;
public AsyncFetch(String searchQuery, int startrow, String type, String filetype){
this.searchQuery=searchQuery;
this.startrow = startrow;
this.type = type;
this.filetype=filetype;
}
@Override
protected void onPreExecute() {
super.onPreExecute();
//this method will be running on UI thread
pdLoading.setMessage("\tLoading...");
pdLoading.setCancelable(false);
pdLoading.show();
}
@Override
protected String doInBackground(String... params) {
try {
// Enter URL address where your php file resides
url = new URL("http://someurl/json/search.php");
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return e.toString();
}
try {
// Setup HttpURLConnection class to send and receive data from php and mysql
conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(READ_TIMEOUT);
conn.setConnectTimeout(CONNECTION_TIMEOUT);
conn.setRequestMethod("POST");
// setDoInput and setDoOutput to true as we send and recieve data
conn.setDoInput(true);
conn.setDoOutput(true);
// add parameter to our above url
Uri.Builder builder = new Uri.Builder().appendQueryParameter("searchQuery", searchQuery).appendQueryParameter("startrow", String.valueOf(startrow));
String query = builder.build().getEncodedQuery();
OutputStream os = conn.getOutputStream();
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(os, "UTF-8"));
writer.write(query);
writer.flush();
writer.close();
os.close();
conn.connect();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
return e1.toString();
}
try {
int response_code = conn.getResponseCode();
// Check if successful connection made
if (response_code == HttpURLConnection.HTTP_OK) {
// Read data sent from server
InputStream input = conn.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(input));
StringBuilder result = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
result.append(line);
}
// Pass data to onPostExecute method
return (result.toString());
} else {
return("Connection error");
}
} catch (IOException e) {
e.printStackTrace();
return e.toString();
} finally {
conn.disconnect();
}
}
@Override
protected void onPostExecute(String result) {
//this method will be running on UI thread
pdLoading.dismiss();
List<DataFish> data=new ArrayList<>();
pdLoading.dismiss();
if(result.equals("no rows")) {
Toast.makeText(MainActivity.this, "No Results found for entered query", Toast.LENGTH_LONG).show();
}else{
try {
JSONArray jArray = new JSONArray(result);
// Extract data from json and store into ArrayList as class objects
for (int i = 0; i < jArray.length(); i++) {
JSONObject json_data = jArray.getJSONObject(i);
DataFish fishData = new DataFish();
try {
fishData.fileName = URLDecoder.decode(json_data.getString("file"), "UTF-8");
} catch (Exception e) {
Toast.makeText(MainActivity.this, e.toString(), Toast.LENGTH_LONG).show();
fishData.fileName=json_data.getString("file");
}
fishData.linkName = json_data.getString("link");
fishData.reg_date = json_data.getString("reg_date");
fishData.fileSize = json_data.getString("filesize");
data.add(fishData);
}
mAdapter = new AdapterFish(MainActivity.this, data);
mRVFish.setAdapter(mAdapter);
if(jArray.length()>19)
mScrollListener.setLoading(false);
else
mScrollListener.setLoading(true);
} catch (JSONException e) {
// You to understand what actually error is and handle it appropriately
Toast.makeText(MainActivity.this, e.toString(), Toast.LENGTH_LONG).show();
Toast.makeText(MainActivity.this, result.toString(), Toast.LENGTH_LONG).show();
}
}
}
}
}
EndlessRecyclerOnScrollListener.java
public abstract class EndlessRecyclerOnScrollListener extends
RecyclerView.OnScrollListener {
public static String TAG = EndlessRecyclerOnScrollListener.class.getSimpleName();
private int previousTotal = 0; // The total number of items in the dataset after the last load
private boolean loading = false; // True if we are still waiting for the last set of data to load.
private int visibleThreshold = 0; // The minimum amount of items to have below your current scroll position before loading more.
int firstVisibleItem, visibleItemCount, totalItemCount;
private int current_page = 20;
private LinearLayoutManager mLayoutManager;
public EndlessRecyclerOnScrollListener(LinearLayoutManager linearLayoutManager) {
this.mLayoutManager = linearLayoutManager;
}
@Override
public void onScrolled(RecyclerView mRVFish, int dx, int dy) {
super.onScrolled(mRVFish, dx, dy);
if(dy < 0) {
return;
}
// check for scroll down only
visibleItemCount = mRVFish.getChildCount();
totalItemCount = mLayoutManager.getItemCount();
firstVisibleItem = mLayoutManager.findFirstVisibleItemPosition();
// to make sure only one onLoadMore is triggered
synchronized (this) {
if (!loading && (totalItemCount - visibleItemCount) <= (firstVisibleItem + visibleThreshold)) {
// End has been reached, Do something
current_page=current_page+20;
onLoadMore(current_page);
loading = true;
}
}
}
public void setLoading(boolean loading) {
this.loading = loading;
}
public abstract void onLoadMore(int current_page);
}
答案 0 :(得分:1)
首先,新列表重新创建自己,而不是附加到旧列表。
如果设置新适配器,则交换回收器视图的内容。我想你在下面的代码中做到了
mAdapter = new AdapterFish(MainActivity.this, data);
mRVFish.setAdapter(mAdapter);
要附加数据,您需要将新元素添加到适配器的数据集(数据集,您获取数据以在适配器中绑定视图),然后调用adapter.notifyDataSetChanged()
或更好adapter.notifyItemRangeInserted(int positionStart, int itemCount)
还有一些工具可以优化添加元素,例如DiffUtil
第二,current_page int变量保持其前一次搜索的值并滚动,表示第二次运行AsyncTask时
不确定图书馆开发人员的想法是什么,但最简单的方法是在EndlessRecyclerOnScrollListener
中创建类似于:
public void resetPage() {
current_page = 20;
}
在调用新搜索之前调用它。