Endless RecyclerView with Asynctask using EndlessRecyclerOnS



我有一个搜索查询的活动(使用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);
}

首先,新列表会重新创建自身,而不是追加到旧列表。

如果设置了新适配器,则会交换回收器视图的内容。我想你在下面的代码中做到这一点

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;
}

并在调用新搜索之前调用它。

最新更新