简体   繁体   English

如何在列表视图中添加滑动刷新

[英]How to add swipe-to-refresh in a list view

I am working on a news app and I want to update the ListView every time by swiping down in the MainActivity我正在开发一个新闻应用程序,我想每次通过在MainActivity向下滑动来更新ListView
This is the code of my MainActivity below:这是下面我的MainActivity的代码:

package com.infinitystone.mani.news;

import android.app.LoaderManager;
import android.app.LoaderManager.LoaderCallbacks;
import android.content.Context;
import android.content.Loader;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.os.Bundle;
import android.support.customtabs.CustomTabsIntent;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity implements LoaderCallbacks<List<News>> {

    public static final String LOG_TAG = MainActivity.class.getName();

    private static final int NEWS_LOADER_ID = 1;

    private TextView mEmptyView;

    private NewsAdapter mAdapter;

    private static final String GUARDIAN_REQUEST_URL = "http://content.guardianapis.com/search?order-by=newest&show-fields=thumbnail&page-size=20&api-key=2f3badbb-4a58-44b8-9800-9ee2a0f445f9";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ListView newsList = (ListView) findViewById(R.id.list);

        mEmptyView = (TextView) findViewById(R.id.empty_view);
        newsList.setEmptyView(mEmptyView);

        mAdapter = new NewsAdapter(this, new ArrayList<News>());
        newsList.setAdapter(mAdapter);

        newsList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                News currentNews = mAdapter.getItem(position);
                Uri uri = Uri.parse(currentNews.getUrl());

                CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder();

                builder.setToolbarColor(ContextCompat.getColor(MainActivity.this, R.color.colorPrimary));
                builder.setSecondaryToolbarColor(ContextCompat.getColor(MainActivity.this, R.color.colorPrimaryDark));

                builder.setShowTitle(true);

                final Bitmap backButton = BitmapFactory.decodeResource(getResources(), R.drawable.ic_arrow_back_white_24dp);
                builder.setCloseButtonIcon(backButton);

                CustomTabsIntent customTabsIntent = builder.build();
                customTabsIntent.launchUrl(MainActivity.this, uri);

            }
        });

        ConnectivityManager connMgr = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);

        NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();

        if(networkInfo != null && networkInfo.isConnected()){
            LoaderManager loaderManager = getLoaderManager();

            loaderManager.initLoader(NEWS_LOADER_ID, null, this);
        }

        else {
            View loadingIndicator = findViewById(R.id.loading_indicator);
            loadingIndicator.setVisibility(View.GONE);

            mEmptyView.setText(R.string.no_internet);
        }
    }

    @Override
    public Loader<List<News>> onCreateLoader(int i, Bundle bundle) {
        // Create a new loader for the given URL
        return new NewsLoader(this, GUARDIAN_REQUEST_URL);
    }

    @Override
    public void onLoadFinished(Loader<List<News>> loader, List<News> news) {
        View loadingIndicator = findViewById(R.id.loading_indicator);
        loadingIndicator.setVisibility(View.GONE);

        mEmptyView.setText(R.string.no_news);

        mAdapter.clear();

        if (news != null && !news.isEmpty()) {
            mAdapter.addAll(news);
        }
    }

    @Override
    public void onLoaderReset(Loader<List<News>> loader) {
        // Loader reset, so we can clear out our existing data.
        mAdapter.clear();
    }
}  

I have already added the android.support.v4.widget.SwipeRefreshLayout in my activity_main.xml file我已经在我的activity_main.xml文件中添加了android.support.v4.widget.SwipeRefreshLayout
How can I implement the SwipeRefreshLayout in java code ?如何在 Java 代码中实现SwipeRefreshLayout
Code for fetching the news data:获取新闻数据的代码:

package com.infinitystone.mani.news;


import android.text.TextUtils;
import android.util.Log;

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

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;

import static com.infinitystone.mani.news.MainActivity.LOG_TAG;

public class QueryUtils {


    private QueryUtils() {

    }

    public static List<News> fetchNewsData(String requestUrl) {
        URL url = createUrl(requestUrl);

        String jsonResponse = null;
        try {
            jsonResponse = makeHttpRequest(url);
        } catch (IOException e) {
            Log.e(LOG_TAG, "Problem making the HTTP request.", e);
        }

        List<News> news = extractFeaturesFromJson(jsonResponse);

        return news;
    }

    private static URL createUrl(String stringUrl) {
        URL url = null;
        try {
            url = new URL(stringUrl);
        } catch (MalformedURLException e) {
            Log.e(LOG_TAG, "Problem building the URL ", e);
        }
        return url;
    }

    private static String makeHttpRequest(URL url) throws IOException {
        String jsonResponse = "";

        // If the URL is null, then return early.
        if (url == null) {
            return jsonResponse;
        }

        HttpURLConnection urlConnection = null;
        InputStream inputStream = null;
        try {
            urlConnection = (HttpURLConnection) url.openConnection();
            urlConnection.setReadTimeout(10000 /* milliseconds */);
            urlConnection.setConnectTimeout(15000 /* milliseconds */);
            urlConnection.setRequestMethod("GET");
            urlConnection.connect();

            // If the request was successful (response code 200),
            // then read the input stream and parse the response.
            if (urlConnection.getResponseCode() == 200) {
                inputStream = urlConnection.getInputStream();
                jsonResponse = readFromStream(inputStream);
            } else {
                Log.e(LOG_TAG, "Error response code: " + urlConnection.getResponseCode());
            }
        } catch (IOException e) {
            Log.e(LOG_TAG, "Problem retrieving the earthquake JSON results.", e);
        } finally {
            if (urlConnection != null) {
                urlConnection.disconnect();
            }
            if (inputStream != null) {
                // Closing the input stream could throw an IOException, which is why
                // the makeHttpRequest(URL url) method signature specifies than an IOException
                // could be thrown.
                inputStream.close();
            }
        }
        return jsonResponse;
    }

    private static String readFromStream(InputStream inputStream) throws IOException {
        StringBuilder output = new StringBuilder();
        if (inputStream != null) {
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream, Charset.forName("UTF-8"));
            BufferedReader reader = new BufferedReader(inputStreamReader);
            String line = reader.readLine();
            while (line != null) {
                output.append(line);
                line = reader.readLine();
            }
        }
        return output.toString();
    }

    private static List<News> extractFeaturesFromJson(String newsJSON) {

        if (TextUtils.isEmpty(newsJSON)) {
            return null;
        }

        List<News> news = new ArrayList<>();

        try {
            JSONObject rootObject = new JSONObject(newsJSON);

            JSONObject responseObject = rootObject.getJSONObject("response");

            JSONArray resultsArray = responseObject.getJSONArray("results");

            for (int i = 0; i < resultsArray.length(); i++) {
                JSONObject currentNews = resultsArray.getJSONObject(i);

                String title = currentNews.getString("webTitle");

                String titleUrl = currentNews.getString("webUrl");

                String date = currentNews.getString("webPublicationDate");

                JSONObject fields = currentNews.getJSONObject("fields");

                String thumbnail = fields.getString("thumbnail");

                News news1 = new News(title, thumbnail, date, titleUrl);

                news.add(news1);
            }
        } catch (JSONException e) {
            Log.e("QueryUtils", "Problem parsing the earthquake JSON results", e);
        }

        return news;
    }
}

Get a reference to your swipe to refresh layout.获取对您的滑动以刷新布局的引用。

private SwipeRefreshLayout swipeRefreshLayout;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    swipeRefreshLayout = (SwipeRefreshLayout) view.findViewById(R.id.refresh);

    swipeRefreshLayout.setOnRefreshListener(this);

    // ... your other codes...

}

Now, make your activity implement the listener.现在,让您的活动实现侦听器。

public class MainActivity extends AppCompatActivity implements LoaderCallbacks<List<News>>, SwipeRefreshLayout.OnRefreshListener {

    // ... 

}

Finally implement those methods最后实现这些方法

 @Override
  public void onRefresh(){
     swipeRefreshLayout.setRefreshing(true);

     newsList = fetchNewsData(GUARDIAN_REQUEST_URL);
     mAdapter.notifyDataSetChanged(); 

     swipeRefreshLayout.setRefreshing(false);

  }

EDIT:编辑:

Here is the complete code for MainActivity .这是MainActivity的完整代码。 Please use this and let me know if this works.请使用它并让我知道这是否有效。

import android.app.LoaderManager;
import android.app.LoaderManager.LoaderCallbacks;
import android.content.Context;
import android.content.Loader;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.os.Bundle;
import android.support.customtabs.CustomTabsIntent;
import android.support.v4.content.ContextCompat;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity implements LoaderCallbacks<List<News>>, SwipeRefreshLayout.OnRefreshListener {

    public static final String LOG_TAG = MainActivity.class.getName();

    private static final int NEWS_LOADER_ID = 1;

    private TextView mEmptyView;

    private NewsAdapter mAdapter;

    private static final String GUARDIAN_REQUEST_URL = "http://content.guardianapis.com/search?order-by=newest&show-fields=thumbnail&page-size=20&api-key=2f3badbb-4a58-44b8-9800-9ee2a0f445f9";

    private SwipeRefreshLayout swipeRefreshLayout;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ListView newsList = (ListView) findViewById(R.id.list);

        mEmptyView = (TextView) findViewById(R.id.empty_view);
        newsList.setEmptyView(mEmptyView);

        mAdapter = new NewsAdapter(this, new ArrayList<News>());
        newsList.setAdapter(mAdapter);

        swipeRefreshLayout = (SwipeRefreshLayout) view.findViewById(R.id.refresh);

        swipeRefreshLayout.setOnRefreshListener(this);

        newsList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                News currentNews = mAdapter.getItem(position);
                Uri uri = Uri.parse(currentNews.getUrl());

                CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder();

                builder.setToolbarColor(ContextCompat.getColor(MainActivity.this, R.color.colorPrimary));
                builder.setSecondaryToolbarColor(ContextCompat.getColor(MainActivity.this, R.color.colorPrimaryDark));

                builder.setShowTitle(true);

                final Bitmap backButton = BitmapFactory.decodeResource(getResources(), R.drawable.ic_arrow_back_white_24dp);
                builder.setCloseButtonIcon(backButton);

                CustomTabsIntent customTabsIntent = builder.build();
                customTabsIntent.launchUrl(MainActivity.this, uri);

            }
        });

        updateNewsList();


    }

    private void updateNewsList(){
        ConnectivityManager connMgr = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);

        NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();

        if(networkInfo != null && networkInfo.isConnected()){
            LoaderManager loaderManager = getLoaderManager();

            loaderManager.initLoader(NEWS_LOADER_ID, null, this);
        }

        else {
            View loadingIndicator = findViewById(R.id.loading_indicator);
            loadingIndicator.setVisibility(View.GONE);

            mEmptyView.setText(R.string.no_internet);
        }
    }

    @Override
    public Loader<List<News>> onCreateLoader(int i, Bundle bundle) {
        // Create a new loader for the given URL
        return new NewsLoader(this, GUARDIAN_REQUEST_URL);
    }

    @Override
    public void onLoadFinished(Loader<List<News>> loader, List<News> news) {
        View loadingIndicator = findViewById(R.id.loading_indicator);
        loadingIndicator.setVisibility(View.GONE);

        mEmptyView.setText(R.string.no_news);

        mAdapter.clear();

        if (news != null && !news.isEmpty()) {
            mAdapter.addAll(news);
        }
    }

    @Override
    public void onLoaderReset(Loader<List<News>> loader) {
        // Loader reset, so we can clear out our existing data.
        mAdapter.clear();
    }


    @Override
    public void onRefresh() {
       swipeRefreshLayout.setRefreshing(true);
       updateNewsList();
       swipeRefreshLayout.setRefreshing(false);

    }
}

试试这个响应刷新手势,它应该会有所帮助。

as per my above comment use SwipeRefreshLayout 根据我上面的评论使用SwipeRefreshLayout

The SwipeRefreshLayout should be used whenever the user can refresh the contents of a view via a vertical swipe gesture.只要用户可以通过垂直滑动手势刷新视图的内容,就应该使用 SwipeRefreshLayout。 The activity that instantiates this view should add an OnRefreshListener to be notified whenever the swipe to refresh gesture is completed.实例化此视图的活动应添加一个 OnRefreshListener,以便在完成滑动刷新手势时收到通知。 The SwipeRefreshLayout will notify the listener each and every time the gesture is completed again; SwipeRefreshLayout 会在每次手势再次完成时通知监听器;

than set setOnRefreshListener to your SwipeRefreshLayout比将setOnRefreshListener设置为您的SwipeRefreshLayout

void setOnRefreshListener (SwipeRefreshLayout.OnRefreshListener listener)

Set the listener to be notified when a refresh is triggered via the swipe gesture.设置在通过滑动手势触发刷新时通知侦听器。

sample code示例代码

SwipeRefreshLayout mSwipeRefreshView;
mSwipeRefreshView = (SwipeRefreshLayout) findViewById(R.id.homeScreenSwipeRefreshView);

mSwipeRefreshView.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {

                // make your api request here
            }
        });

when your api request complted than use setRefreshing(false)当您的 api 请求完成而不是使用setRefreshing(false)

 setRefreshing(boolean refreshing)

Notify the widget that refresh state has changed.通知小部件刷新状态已更改。

mSwipeRefreshView.setRefreshing(false);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM