0

所以我在理解(我认为)刷新 UI 的工作原理方面存在问题。我有一个底部导航栏的活动,其中包含 3 个加载片段的项目。每个片段都从互联网加载数据,因此我将这些数据下载到一个线程中,完成后我在 UI 线程上刷新我的 recyclerview。

但问题是当我在导航栏上选择一个项目时,当我立即选择另一个项目时,我的应用程序崩溃,因为数据下载完成并且 UI 线程正在尝试刷新 recyclerview 但我不再在分段

那么我怎样才能避免这种崩溃呢?

这是我的代码:

private void refreshRecyclerView() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                predictionList = ComboBetHTMLParser.getPredictionList();
                updateUI();
            }
        }).start();
    }

    private void updateUI() {
        getActivity().runOnUiThread(new Runnable() {
            @Override
            public void run() {
                adapter = new PredictionAdapter(predictionList);
                recyclerView.setAdapter(adapter);
                adapter.notifyDataSetChanged();
            }
        });
    }

编辑 :

这是错误日志:

                  java.lang.NullPointerException: Attempt to invoke virtual method 'void android.support.v4.app.FragmentActivity.runOnUiThread(java.lang.Runnable)' on a null object reference
                      at com.projects.morgan.kingwin.Fragments.SafeFragment.updateUI(SafeFragment.java:61)
                      at com.projects.morgan.kingwin.Fragments.SafeFragment.access$100(SafeFragment.java:20)
                      at com.projects.morgan.kingwin.Fragments.SafeFragment$1.run(SafeFragment.java:55)
                      at java.lang.Thread.run(Thread.java:764)

主Activity底部导航条码:

bottomNavigationBar.setTabSelectedListener(new BottomNavigationBar.OnTabSelectedListener() {
            @Override
            public void onTabSelected(int position) {
                displayOnSelectedScreen(position);
            }

            @Override
            public void onTabUnselected(int position) {
                Log.d("TEST", "onTabUnselected:" + position);
            }

            @Override
            public void onTabReselected(int position) {
                Log.d("TEST", "onTabReselected:");
            }
        });



private void displayOnSelectedScreen(int position) {
        // Begin the transaction
        FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
        Fragment fragment = null;
        switch (position) {
            case 0:
                if (accueilFragment == null) {
                    accueilFragment = new AccueilFragment();
                }
                fragment = accueilFragment;
                break;
            case 1:
                if (predictionsFragment == null) {
                    predictionsFragment = new PredictionsFragment();
                }
                fragment = predictionsFragment;
                break;
            case 2:
                if (safeFragment == null) {
                    safeFragment = new SafeFragment();
                }
                fragment = safeFragment;
                break;
        }
        ft.replace(R.id.content_frame,fragment).commit();
    }

片段代码:

public class SafeFragment extends Fragment {

    private List<Prediction> predictionList = new ArrayList<>();
    private RecyclerView recyclerView;
    private PredictionAdapter adapter;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        View view = inflater.inflate(R.layout.recycler_view_pronos, container, false);
        initRecyclerView(view);
        return view;
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        if (predictionList.size() == 0) {
            refreshRecyclerView();
        }
    }

    private void initRecyclerView(View view) {
        recyclerView = (RecyclerView) view.findViewById(R.id.recycler_view);
        recyclerView.setHasFixedSize(true);
        adapter = new PredictionAdapter(predictionList);
        recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
        recyclerView.setAdapter(adapter);
    }

    private void refreshRecyclerView() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                predictionList = InternetData.getPredictionList();
                updateUI();
            }
        }).start();
    }

    private void updateUI() {
        getActivity().runOnUiThread(new Runnable() {
            @Override
            public void run() {
                adapter = new PredictionAdapter(predictionList);
                recyclerView.setAdapter(adapter);
                adapter.notifyDataSetChanged();
            }
        });
    }
}
4

4 回答 4

0

请提供整个片段代码及其宿主活动。您的案例似乎存在一些并发问题。

于 2018-08-14T07:27:01.660 回答
0

在调用 runOnUiThread 方法之前添加一个空指针检查,如下所示

if(getActivity() != null){
    getActivity().runOnUiThread(new Runnable() {
        @Override
        public void run() {
            adapter = new PredictionAdapter(predictionList);
            recyclerView.setAdapter(adapter);
            adapter.notifyDataSetChanged();
        }
    });
}

因为您的片段不再存在,所以它的 getActivity() 方法返回 null。这应该避免崩溃。

于 2018-08-14T07:37:56.387 回答
0

我认为问题出在您试图获取 getActivity() 的引用以在 ui 线程上运行时。

private void updateUI() {
    getActivity().runOnUiThread(new Runnable() {
        @Override
        public void run() {
            adapter = new PredictionAdapter(predictionList);
            recyclerView.setAdapter(adapter);
            adapter.notifyDataSetChanged();
        }
    });
}

如果您不在片段中并尝试调用getActivity()它将返回null对象。所以null在调用之前添加检查getActivity()将解决问题。就像是

    if(getActivity() !=null){
    //call the ui thread
      getActivity().runOnUiThread(new Runnable() {
            @Override
            public void run() {
                adapter = new PredictionAdapter(predictionList);
                recyclerView.setAdapter(adapter);
                adapter.notifyDataSetChanged();
            }
        });
    }
于 2018-08-14T07:37:59.940 回答
0

您必须首先检查您当前的活动或片段是否存在。因为您正在尝试更新 UI,但当时可能片段或活动不存在。您可以使用以下代码执行此操作:

if (getActivity() != null) {
            getActivity().runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    adapter = new PredictionAdapter(predictionList);
                    recyclerView.setAdapter(adapter);
                    adapter.notifyDataSetChanged();
                }
            });
        }
于 2018-08-14T07:47:17.497 回答