【问题标题】:Network calls in fragments片段中的网络调用
【发布时间】:2017-09-13 11:51:08
【问题描述】:

我正在制作一个新闻应用程序,其中有 3 个标签,分别是趋势、最新和流行。我已经实现了选项卡布局。现在我必须在选择每个片段时显示列表。我在下面使用谷歌新闻 API

https://newsapi.org/v1/articles?source=google-news&sortBy=top

现在我想根据选择的标签过滤来自 API 的数据,例如如果选择了流行标签,那么 URL 应该是 https://newsapi.org/v1/articles?source=google-news&sortBy=popular,它将显示在相应的片段中。

我在第一个选项卡中进行了网络调用,它的工作正常。但是当我切换标签时它崩溃了。所以我很困惑如何根据选择的标签进行网络调用。

这是我的主要活动:

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

        initializeViews();


        setSupportActionBar(toolbar);
        getSupportActionBar().setDisplayShowHomeEnabled(true);
        getSupportActionBar().setDisplayUseLogoEnabled(true);
        setupViewPager(viewPager);
        tabLayout.setupWithViewPager(viewPager);
    }

    private void setupViewPager(ViewPager viewPager) {

        ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
        adapter.addFragment(new TopStories(), "top stories");
        adapter.addFragment(new Trending(), "trending");
        adapter.addFragment(new Latest(), "latest");
        adapter.addFragment(new Popular(), "popular");
        viewPager.setAdapter(adapter);
    }

    private void initializeViews() {
        toolbar = (Toolbar) findViewById(R.id.toolbar);
        viewPager = (ViewPager) findViewById(R.id.viewpager);
        tabLayout = (TabLayout) findViewById(R.id.tabs);
    }


     class ViewPagerAdapter extends FragmentPagerAdapter {

         private final List<Fragment> mFragmentList = new ArrayList<>();
         private final List<String> mFragmentTitleList = new ArrayList<>();

         public ViewPagerAdapter(FragmentManager manager) {
             super(manager);
         }

         @Override
         public Fragment getItem(int position) {
             return mFragmentList.get(position);
         }

         @Override
         public int getCount() {
             return mFragmentList.size();
         }

         public void addFragment(Fragment fragment, String title) {
             mFragmentList.add(fragment);
             mFragmentTitleList.add(title);
         }

         @Override
         public CharSequence getPageTitle(int position) {
             return mFragmentTitleList.get(position);
         }
     } 

片段1:

 public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

        View rootView = inflater.inflate(R.layout.top_stories,container,false);
        if (ParamConstants.API_KEY.isEmpty()) {
            Toast.makeText(getContext(), "Please obtain your API KEY first from themoviedb.org", Toast.LENGTH_LONG).show();

        }

        recyclerView = (RecyclerView)rootView.findViewById(R.id.news_recycle);
        recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));

        fetchNews(recyclerView);

        return rootView;
    }

    private void fetchNews(final RecyclerView rv) {
        ApiInterface apiService = ApiClient.getClient().create(ApiInterface.class);
        Call<JsonElement> call = apiService.getNews("google-news", "top", ParamConstants.API_KEY);
        call.enqueue(new Callback<JsonElement>() {
            @Override
            public void onResponse(Call<JsonElement> call, Response<JsonElement> response) {
                Log.d("resonse", response.toString());
                JsonElement object = response.body();
                Type listType = new TypeToken<List<News>>() {
                }.getType();
                news = new Gson().fromJson(object.getAsJsonObject().getAsJsonArray("articles"), listType);
                rv.setAdapter(new NewsAdapter(news, R.layout.news_list_item, getContext()));
                recyclerView.addItemDecoration(new DividerItemDecoration(getContext(),DividerItemDecoration.VERTICAL_LIST));
            }

            @Override
            public void onFailure(Call<JsonElement> call, Throwable t) {
                Log.e(TAG, t.toString());
            }
        });


        Call<JsonElement> source = apiService.getSources("", "", "");
        source.enqueue(new Callback<JsonElement>() {
            @Override
            public void onResponse(Call<JsonElement> call, Response<JsonElement> response) {
                Log.d("sources", response.body().toString());

                Type listType = new TypeToken<List<NewsResponse>>() {
                }.getType();
                newsResponse = new Gson().fromJson(response.body().getAsJsonObject().getAsJsonArray("sources"), listType);
                newsResponse.get(0).getCategory().toString();
            }

            @Override
            public void onFailure(Call<JsonElement> call, Throwable t) {
                Log.e("sourcesfailure", t.toString());
            }
        });
    }

片段2:

public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

        View rootView = inflater.inflate(R.layout.trending_fragment,container,false);


        if (ParamConstants.API_KEY.isEmpty()) {
            Toast.makeText(getContext(), "Please obtain your API KEY first from themoviedb.org", Toast.LENGTH_LONG).show();

        }

        recyclerView = (RecyclerView)rootView.findViewById(R.id.news_recycle);
        recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));

        fetchTrendingNews(recyclerView);

return rootView;

    }

    private void fetchTrendingNews(final RecyclerView recyclerView) {

        ApiInterface apiService = ApiClient.getClient().create(ApiInterface.class);
        Call<JsonElement> call = apiService.getNews("BBC News", "popular", ParamConstants.API_KEY);
        call.enqueue(new Callback<JsonElement>() {
            @Override
            public void onResponse(Call<JsonElement> call, Response<JsonElement> response) {
                Log.d("resonse", response.toString());
                JsonElement object = response.body();
                Type listType = new TypeToken<List<News>>() {
                }.getType();
                news = new Gson().fromJson(object.getAsJsonObject().getAsJsonArray("articles"), listType);
                recyclerView.setAdapter(new NewsAdapter(news, R.layout.news_list_item, getContext()));
                recyclerView.addItemDecoration(new DividerItemDecoration(getContext(),DividerItemDecoration.VERTICAL_LIST));
            }

            @Override
            public void onFailure(Call<JsonElement> call, Throwable t) {
                Log.e(TAG, t.toString());
            }
        });
    }

错误日志:

java.lang.NullPointerException: Attempt to invoke virtual method 'void android.support.v7.widget.RecyclerView.setLayoutManager(android.support.v7.widget.RecyclerView$LayoutManager)' on a null object reference
                                                                             at com.kotlin.whatshappening.activity.fragment.Trending.onCreateView(Trending.java:65)
                                                                             at android.support.v4.app.Fragment.performCreateView(Fragment.java:2184)
                                                                             at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1298)
                                                                             at android.support.v4.app.FragmentManagerImpl.moveFragmentsToInvisible(FragmentManager.java:2323)
                                                                             at android.support.v4.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2136)
                                                                             at android.support.v4.app.FragmentManagerImpl.optimizeAndExecuteOps(FragmentManager.java:2092)
                                                                             at android.support.v4.app.FragmentManagerImpl.execSingleAction(FragmentManager.java:1969)
                                                                             at android.support.v4.app.BackStackRecord.commitNowAllowingStateLoss(BackStackRecord.java:620)
                                                                             at android.support.v4.app.FragmentPagerAdapter.finishUpdate(FragmentPagerAdapter.java:143)
                                                                             at android.support.v4.view.ViewPager.populate(ViewPager.java:1268)
                                                                             at android.support.v4.view.ViewPager.populate(ViewPager.java:1116)
                                                                             at android.support.v4.view.ViewPager.onMeasure(ViewPager.java:1642)
                                                                             at android.view.View.measure(View.java:18809)
                                                                             at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5954)
                                                                             at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1465)
                                                                             at android.widget.LinearLayout.measureVertical(LinearLayout.java:748)
                                                                             at android.widget.LinearLayout.onMeasure(LinearLayout.java:630)
                                                                             at android.view.View.measure(View.java:18809)
                                                                             at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5954)
                                                                             at android.widget.FrameLayout.onMeasure(FrameLayout.java:194)
                                                                             at android.support.v7.widget.ContentFrameLayout.onMeasure(ContentFrameLayout.java:139)
                                                                             at android.view.View.measure(View.java:18809)
                                                                             at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5954)
                                                                             at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1465)
                                                                             at android.widget.LinearLayout.measureVertical(LinearLayout.java:748)
                                                                             at android.widget.LinearLayout.onMeasure(LinearLayout.java:630)
                                                                             at android.view.View.measure(View.java:18809)
                                                                             at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5954)
                                                                             at android.widget.FrameLayout.onMeasure(FrameLayout.java:194)
                                                                             at android.view.View.measure(View.java:18809)
                                                                             at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5954)
                                                                             at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1465)
                                                                             at android.widget.LinearLayout.measureVertical(LinearLayout.java:748)
                                                                             at android.widget.LinearLayout.onMeasure(LinearLayout.java:630)
                                                                             at android.view.View.measure(View.java:18809)
                                                                             at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5954)
                                                                             at android.widget.FrameLayout.onMeasure(FrameLayout.java:194)
                                                                             at com.android.internal.policy.PhoneWindow$DecorView.onMeasure(PhoneWindow.java:2643)
                                                                             at android.view.View.measure(View.java:18809)
                                                                             at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:2112)
                                                                             at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1228)
                                                                             at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1464)
                                                                             at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1119)
                                                                             at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6060)
                                                                             at android.view.Choreographer$CallbackRecord.run(Choreographer.java:858)
                                                                             at android.view.Choreographer.doCallbacks(Choreographer.java:670)
                                                                             at android.view.Choreographer.doFrame(Choreographer.java:606)
                                                                             at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:844)
                                                                             at android.os.Handler.handleCallback(Handler.java:746)
                                                                             at android.os.Handler.dispatchMessage(Handler.java:95)
                                                                             at android.os.Looper.loop(Looper.java:148)
                                                                             at android.app.ActivityThread.main(ActivityThread.java:5443)
                                                                             at java.lang.reflect.Method.invoke(Native Method)
                                                                            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.

那么我如何根据每个选定的选项卡进行网络调用。

【问题讨论】:

  • 显示你的错误日志。
  • @gaurav 检查 trending_fragment.xml 是否包含 ID 为 news_recycle 的 RecyclerView ?
  • @DivySoni 感谢您的帮助
  • @gauravtiwari 你的问题解决了吗?
  • @DivySoni 是的,它解决了,你正确地提到了错误。

标签: android android-fragments tabs


【解决方案1】:

您的片段可能会在收到服务器响应之前调用 onDestroyView() 方法,在这种情况下,如果您对 UI 元素(视图)进行任何操作,它会给出 NullPointerException,因此请务必检查它:

@Override
            public void onResponse(Call<JsonElement> call, Response<JsonElement> response) {
                if(getActivity==null){
                return;
                }
                //do your UI code here
            }

            @Override
            public void onFailure(Call<JsonElement> call, Throwable t) {
                Log.e(TAG, t.toString());
                if(getActivity==null){
                return;
                }
                //do your UI code here
            }

【讨论】:

    【解决方案2】:

    您可以设置 OnPageChangeListener 来查看分页器,在 onPageSelected 方法中您将获得当前选择的片段(分页器位置),然后您可以根据选择的片段调用特定的 api 调用。

    例如。

    viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() { @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

            }
    
            @Override
            public void onPageSelected(int position) {
         //  here you will get currently selected fragment
         //  selected fragment - adapter.getItem(position);
            }
    
            @Override
            public void onPageScrollStateChanged(int state) {
    
            }
        });
    

    【讨论】:

      【解决方案3】:

      java.lang.NullPointerException:尝试在空对象引用上调用虚拟方法“void android.support.v7.widget.RecyclerView.setLayoutManager(android.support.v7.widget.RecyclerView$LayoutManager)”

      此行表示您尝试加载的 recyclerview 没有附加布局管理器。

      替换

      rv.setAdapter(new NewsAdapter(news, R.layout.news_list_item, getContext()))
      

      recyclerView.setAdapter(new NewsAdapter(news, R.layout.news_list_item, getContext()));
      

      在 Fragment1 类中

      【讨论】:

        【解决方案4】:

        1.) 在 setUpViewPager 方法中创建一个 Fragment 添加 3 次。

        2.) 并为该 Fragment 对象设置参数,并带有一些屏幕区分号。

        3.) 在该 Fragment 中,通过 getArguments 方法获取该屏幕编号。

        4.) 现在根据该数字,在单个 Fragment 中调用您的 api。

        您无需创建三个不同的片段即可仅在 RecyclerView 中显示数据。

        【讨论】:

          【解决方案5】:

          试试这个... 希望对您有所帮助。

          Context mContext = rootView.getContext();
          
          LinearLayoutManager  mLinearLayoutManager = new LinearLayoutManager(mContext, LinearLayoutManager.VERTICAL, false);
          
          recyclerView.setLayoutManager(mLinearLayoutManager)
          

          而你想获得当前的标签标题, 然后,使用它,您可以获得当前的当前标签标题:

          adapter.getPageTitle(viewpager.getCurrentItem());
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2020-11-30
            • 1970-01-01
            • 1970-01-01
            • 2013-05-05
            • 2013-07-02
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多