Java Android 滚动到底部并获取新数据后总是转到第一个数据/页面(顶部回收 View )

标签 java android android-recyclerview httpurlconnection fetch

获取新数据后,应用程序始终转到第一页。因此,我必须(再次)滚动到底部才能在回收 View 上查看新数据。

代码

这是我的代码。我该如何解决我的问题?

package tonnyferiandi.lastproject;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Base64;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ProgressBar;
import android.widget.Toast;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

public class tab_feed extends Fragment {

    private List<tab_feedItem> feedsList;
    private RecyclerView mRecyclerView;
    private tab_feedAdapter adapter;
    private ProgressBar progressBar;
    private Bitmap photone;
    private Bitmap photono;
    private boolean load = true;
    public int page=0;
    public View v;
    public String url;
    LinearLayoutManager layoutManager;
    int pastVisiblesItems, visibleItemCount, totalItemCount;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        v = inflater.inflate(R.layout.fragment_tab_feed, container, false);

        mRecyclerView = (RecyclerView) v.findViewById(R.id.recycler_view);
        mRecyclerView.setHasFixedSize(true);
        layoutManager = new LinearLayoutManager(getActivity());
        mRecyclerView.setLayoutManager(layoutManager);
        progressBar = (ProgressBar) v.findViewById(R.id.progress_bar);
        progressBar.setVisibility(View.VISIBLE);
        feedsList = new ArrayList<>();
        // Downloading data from below url
        url = "http://tukoe.com/feed/getfeed.php?page="+String.valueOf(page);
        new AsyncHttpTask().execute(url);
        return v;
    }

    public class AsyncHttpTask extends AsyncTask<String, Void, Integer> {

        @Override
        protected void onPreExecute() {
            //setProgressBarIndeterminateVisibility(true);
            progressBar.setVisibility(View.VISIBLE);
        }

        @Override
        protected Integer doInBackground(String... params) {
            Integer result = 0;
            HttpURLConnection urlConnection;
            try {
                URL url = new URL(params[0]);
                urlConnection = (HttpURLConnection) url.openConnection();
                int statusCode = urlConnection.getResponseCode();

                // 200 represents HTTP OK
                if (statusCode == 200) {
                    BufferedReader r = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
                    StringBuilder response = new StringBuilder();
                    String line;
                    while ((line = r.readLine()) != null) {
                        response.append(line);
                    }
                    parseResult(response.toString());
                    result = 1; // Successful
                } else {
                    result = 0; //"Failed to fetch data!";
                }
            } catch (Exception e) {
                Log.d("RecyclerView", e.getLocalizedMessage());
            }
            return result; //"Failed to fetch data!";
        }

        @Override
        protected void onPostExecute(Integer result) {
            // Download complete. Let us update UI
            progressBar.setVisibility(View.GONE);

            if (result == 1) {
                scroll();
                page++;
            } else {
                Toast.makeText(getActivity().getApplicationContext(), "Failed to fetch data!", Toast.LENGTH_SHORT).show();
            }
        }
    }

    private void parseResult(String result) {
        try {
            JSONObject response = new JSONObject(result);
            JSONArray posts = response.optJSONArray("result");

            for (int i = 0; i < posts.length(); i++) {
                JSONObject post = posts.optJSONObject(i);
                tab_feedItem item = new tab_feedItem();
                if(!post.getString("title").equals(null)){
                    load = true;
                }
                item.setTitle(post.optString("title"));
                photone = decodeBase64(post.optString("photo"));
                int outWidth;
                int outHeight;
                int inWidth = photone.getWidth();
                int inHeight = photone.getHeight();
                if(inWidth > inHeight){
                    outWidth = 768;
                    outHeight = (inHeight * 768) / inWidth;
                } else {
                    outHeight = 768;
                    outWidth = (inWidth * 768) / inHeight;
                }
                photono = Bitmap.createScaledBitmap(photone, outWidth, outHeight, false);
                item.setThumbnail(photono);

                feedsList.add(item);
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    public static Bitmap decodeBase64(String input){
        byte[] decodeByte = Base64.decode(input, 0);
        return BitmapFactory.decodeByteArray(decodeByte, 0, decodeByte.length);
    }

    public void scroll(){
        adapter = new tab_feedAdapter(getActivity(), feedsList);
        mRecyclerView.setAdapter(adapter);
        mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);
                if (dy > 0) //check for scroll down
                {
                    visibleItemCount = mRecyclerView.getChildCount();
                    totalItemCount = layoutManager.getItemCount();
                    pastVisiblesItems = layoutManager.findFirstVisibleItemPosition();

                    if (load) {
                        if ((visibleItemCount + pastVisiblesItems) >= totalItemCount) {
                            load = false;
                            url = "http://tukoe.com/feed/getfeed.php?page="+String.valueOf(page);
                            new AsyncHttpTask().execute(url);
                        }
                    }
                }
            }
        });
    }
}

问题

  • 我必须更改哪一部分?

  • 哪个部分使它进入顶部/首页或回收 View 上的第一个数据?

最佳答案

当您完成获取新数据时,您似乎正在重新创建适配器。这就是导致您滚动回到顶部的原因。我建议不要重新创建适配器,而是更新项目并将更改通知适配器。

首先,我想指出您正在从 AsyncTask 中引用 Fragment 中的数据。这是一个坏主意,因为它可能会导致并发问题。您的 AsyncTask 应该只引用它自己的变量。我建议您的 AsyncTask 结果返回一个 tab_feed 项目列表,您可以使用它来更新您的 UI。

首先,您应该只在创建 Fragment 时调用 scroll() 方法一次。初始化适配器时可以使用空数组,因为无论如何我们很快就会更新它们。

获取完成后在您的 fragment 中:

    @Override
    protected void onPostExecute(List<tab_feedItem> result) {
        // Download complete. Let us update UI
        progressBar.setVisibility(View.GONE);

        if (result != null) {
            adapter.updateItems(result);
            adapter.notifyDataSetChanged();
        } else {
            Toast.makeText(getActivity().getApplicationContext(), "Failed to fetch data!", Toast.LENGTH_SHORT).show();
        }
    }

在你的适配器内部:

public void updateItems(List<tab_feedItem> feedItems){
    this.items.clear();
    this.items.addAll(feeditems);
}

这应该可以解决您遇到的问题。更快的解决方案是保存滚动位置并在重新创建适配器后再次加载它。我建议不要这样做,因为它不能解决你潜在的并发问题,而且很草率。上述建议将需要对您的代码进行一些重大更改,但这是实现您尝试执行的操作的更正确方法。祝你好运!

关于Java Android 滚动到底部并获取新数据后总是转到第一个数据/页面(顶部回收 View ),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37771894/

相关文章:

java - hibernate : limit rows in a table

java - 如何将字节数组转换为人类可读的格式?

android - 暂停和恢复 ActivityGroup 中的子 Activity

android - MadiaStreamTrack 缩放功能未在 Android WebView 中返回,但适用于 Chrome

android - 什么是更新 RecyclerView 中大量移动的项目(交换)和即时用户反馈的良好实现?

java - MediaStore.Images.Media.getBitmap 意外失败

java - ProcessBuilder 重定向输出

android - 更改 Facebook 和 Google 的登录按钮形状和样式

java - 尽管获得了正确的数据,为什么 RecyclerView 适配器没有正确更新(只是第一次)?

android - Arraylist 作为接口(interface)中的参数在 Android RecyclerViewAdapter 中发生 NullPointer Exception