如何使loaderManager.initLoader在片段中工作? [英] How to get loaderManager.initLoader working within a fragment?

查看:48
本文介绍了如何使loaderManager.initLoader在片段中工作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经做出了大多数kris larson建议的更改,现在我没有从onCreateLoader返回正确的类型

I've made the changes suggested by the most kind kris larson, and I'm now not returning the right type from onCreateLoader

return new StoriesLoader(getContext(), uriBuilder.toString());

StoriesLoader:

StoriesLoader:

import android.content.AsyncTaskLoader;
import android.content.Context;

import java.util.List;

/**
 * Loads a list of news stories by using an AsyncTask to perform the
 * network request to the given URL.
 */
public class StoriesLoader extends AsyncTaskLoader<List<NewsStory>> {

    /** Tag for log messages */
    private static final String LOG_TAG = StoriesLoader.class.getName();

    /** Query URL */
    private String mUrl;

    /**
     * Constructs a new {@link StoriesLoader}.
     *
     * @param context of the activity
     * @param url to load data from
     */
    public StoriesLoader(Context context, String url) {
        super(context);
        mUrl = url;
    }

    @Override
    protected void onStartLoading() {
        forceLoad();
    }

    /**
     * This is on a background thread.
     */
    @Override
    public List<NewsStory> loadInBackground() {
        if (mUrl == null) {
            return null;
        }

        // Perform the network request, parse the response, and extract a list of news stories.
        List<NewsStory> newsStories = QueryUtils.fetchNewsStoryData(mUrl);
        return newsStories;
    }
}

我认为我使用AsyncTaskLoader是正确的,但是我不知道如何包装/转换返回的内容,所以它是

I think I'm right to use an AsyncTaskLoader, but I don't get how to wrap / cast what is returned so it's a

Loader<List<NewsStory>>

我的想法错了吗?我是否必须放弃AsyncTaskLoader?~~~

Is my thinking wrong? Do I have to ditch the AsyncTaskLoader? ~~~

StoriesLoader从

StoriesLoader returns List, from

    /**
 * This is on a background thread.
 */
@Override
public List<NewsStory> loadInBackground() {
    if (mUrl == null) {
        return null;
    }

    // Perform the network request, parse the response, and extract a list of earthquakes.
    List<NewsStory> newsStories = QueryUtils.fetchNewsStoryData(mUrl);
    return newsStories;
}

我尝试了这些,但无济于事:

I've tried these, to no avail:

return new Loader<(new StoriesLoader(getContext(), uriBuilder.toString()))>();
return new Loader<>(new StoriesLoader(getContext(), uriBuilder.toString()));

如果您在Kris那里,您的更正将不胜感激.

If you're out there Kris, your corrections are well appreciated.

~~~~~~~~~~Studio抱怨

~~~~~~~~~ Studio is complaining

第3个自变量类型错误.成立:'com.newsreader.guardian.guardiantech.ListOfStoriesFragment',必需的:'android.support.v4.app.LoaderManager.LoaderCallbacks'

Wrong 3rd argument type. Found: 'com.newsreader.guardian.guardiantech.ListOfStoriesFragment', required: 'android.support.v4.app.LoaderManager.LoaderCallbacks'

见到这个

loaderManager.initLoader(mPage, null, this);

我相信它想要一种方法来引用加载程序回调作为第三个参数,它需要一个映射到它们所在的位置,对吗?

I believe it wants a way to reference the loader callbacks as the third parameter, it needs a map to where they are, is this right?

我在一个片段中使用了Loader,因此使它出轨了.我尝试将第三个参数更改为getActivity(),getContext(),尝试ListOfStoriesFragment,但都无济于事.

I'm using the Loader in a fragment so that has derailed it. I've tried changing the third parameter to getActivity(), getContext(), tried ListOfStoriesFragment, all to no avail.

该Fragment确实实现了LoaderCallbacks接口-回调位于其下方,所以为什么不起作用?

The Fragment does implement the LoaderCallbacks interface - the callbacks are beneath it, so why doesn't it work?

我尝试了Android Studio的建议修复程序.实现v4.app.LoadManager回调,但这打破了很多东西.

I tried Android Studio's suggested fixes. Implement v4.app.LoadManager callbacks, but that broke a world of stuff.

我该如何解决?我可以通过导入其他内容来解决此问题吗?
对此问题表示歉意.

How do I fix this? Can I fix this by importing something different?
Apologies for the question.

import android.content.Context;
import android.content.Intent;
import android.content.Loader;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.LoaderManager;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.TextView;

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

import static com.newsreader.guardian.guardiantech.BuildConfig.API_KEY;

/**
 * Initiates a loader to get JSON from The Guardian
 * updates UI with info when the data has returned
 */

public class ListOfStoriesFragment extends Fragment
        implements android.app.LoaderManager.LoaderCallbacks<List<NewsStory>> {
    /** String for tabs */
    public static final String ARG_PAGE = "ARG_PAGE";
    private int mPage;

    private static final String TAG = ListOfStoriesFragment.class.getName();

    /** URL for earthquake data from the USGS dataset */
    private static final String GUARDIAN_REQUEST_URL =
            "http://content.guardianapis.com/search";

    /**
     * Constant value for the news story loader ID. We can choose any integer.
     * This really only comes into play if you're using multiple loaders.
     */
    private static final int NEWSSTORY_LOADER_ID = 1;

    /** Adapter for the list of newsStories */
    private NewsStoryAdapter mAdapter;

    /** TextView that is displayed when the list is empty */
    private TextView mEmptyStateTextView;

    /** more tabs stuff */
    public static ListOfStoriesFragment newInstance(int page) {
        Bundle args = new Bundle();
        args.putInt(ARG_PAGE, page);
        ListOfStoriesFragment fragment = new ListOfStoriesFragment();
        fragment.setArguments(args);
        return fragment;
    }
    /** needed for tabs?! */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mPage = getArguments().getInt(ARG_PAGE);
    }
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_stories, container, false);

        // Find a reference to the {@link ListView} in the layout
        ListView newsStoryListView = (ListView) rootView.findViewById(R.id.list);

        mEmptyStateTextView = (TextView) rootView.findViewById(R.id.empty_view);
        newsStoryListView.setEmptyView(mEmptyStateTextView);

        // Create a new adapter that takes an empty list of NewsStory as input
        mAdapter = new NewsStoryAdapter(getContext(), new ArrayList<NewsStory>());

        // Set the adapter on the {@link ListView}
        // so the list can be populated in the user interface
        newsStoryListView.setAdapter(mAdapter);


        // Get a reference to the ConnectivityManager to check state of network connectivity
        ConnectivityManager connMgr = (ConnectivityManager)
                getActivity().getSystemService(Context.CONNECTIVITY_SERVICE);

        // Get details on the currently active default data network
        NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();

        // If there is a network connection, fetch data
        if (networkInfo != null && networkInfo.isConnected()) {
            // Get a reference to the LoaderManager, in order to interact with loaders.
            LoaderManager loaderManager = getLoaderManager();

            // Initialize the loader. Pass in the int ID constant defined above and pass in null for
            // the bundle. Pass in this activity for the LoaderCallbacks parameter (which is valid
            // because this activity implements the LoaderCallbacks interface).
            //loaderManager.initLoader(NEWSSTORY_LOADER_ID, null, this);

            // number the loaderManager with mPage as may be requesting up to three lots of JSON for each tab
            loaderManager.initLoader(mPage, null, this);
        } else {
            // Otherwise, display error
            // First, hide loading indicator so error message will be visible
            View loadingIndicator = rootView.findViewById(R.id.loading_indicator);
            loadingIndicator.setVisibility(View.GONE);

            // Update empty state with no connection error message
            mEmptyStateTextView.setText(R.string.no_internet_connection);
        }

        return rootView;
    }

    @Override
    public Loader<List<NewsStory>> onCreateLoader(int i, Bundle bundle) {

        String searchTerm;
        switch(mPage) {
            case 0:
                searchTerm = "windows";
                break;
            case 1:
                searchTerm = "android";
                break;
            default:
                searchTerm = "android wear";
        }

        Uri baseUri = Uri.parse(GUARDIAN_REQUEST_URL);
        Uri.Builder uriBuilder = baseUri.buildUpon();

        uriBuilder.appendQueryParameter("q", searchTerm);
        uriBuilder.appendQueryParameter("api-key", API_KEY);
        uriBuilder.build();

        Log.wtf(TAG, uriBuilder.toString());

        return new StoriesLoader(getContext(), uriBuilder.toString());
    }

    @Override
    public void onLoadFinished(Loader<List<NewsStory>> loader, List<NewsStory> newsStories) {
        // Hide loading indicator because the data has been loaded
        View loadingIndicator = getView().findViewById(R.id.loading_indicator);
        loadingIndicator.setVisibility(View.GONE);

        // Set empty state text to display "No stories found."
        mEmptyStateTextView.setText(R.string.no_news_stories);

        // Clear the adapter of previous newsStories
        mAdapter.clear();

        // If there is a valid list of {@link NewsStory}s, then add them to the adapter's
        // data set. This will trigger the ListView to update.
        if (newsStories != null && !newsStories.isEmpty()) {
            mAdapter.addAll(newsStories);
        }
    }

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


}

推荐答案

该Fragment确实实现了LoaderCallbacks接口-回调位于其下方,所以为什么不起作用?

The Fragment does implement the LoaderCallbacks interface - the callbacks are beneath it, so why doesn't it work?

因为您要混合使用支持库类和平台类.

Because you are mixing support library classes with platform classes.

android.content.Loader android.support.v4.app.LoaderManager

           LoaderManager loaderManager = getLoaderManager();

返回一个 android.support.v4.app.LoaderManager ,因此

           loaderManager.initLoader(mPage, null, this);

要进行编译,您的片段将需要实现 android.support.v4.app.LoaderManager.LoaderCallbacks ,而不是 android.app.LoaderManager.LoaderCallbacks .

to compile, your fragment will need to implement android.support.v4.app.LoaderManager.LoaderCallbacks, not android.app.LoaderManager.LoaderCallbacks.

我多次遇到这个问题.

我假设您需要支持库类.

I will assume you want the support library classes.

更改

import android.content.Loader;

import android.support.v4.content.Loader;

更改

public class ListOfStoriesFragment extends Fragment
        implements android.app.LoaderManager.LoaderCallbacks<List<NewsStory>> {

public class ListOfStoriesFragment extends Fragment
        implements LoaderManager.LoaderCallbacks<List<NewsStory>> {

这应该可以解决您的问题.

and that should fix your problem.

确保 StoriesLoader 扩展了 android.support.v4.app.Loader ,而不是 android.app.Loader .检查您的导入声明.

Make sure StoriesLoader extends android.support.v4.app.Loader and not android.app.Loader. Check your import statements.

这篇关于如何使loaderManager.initLoader在片段中工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆