ViewPager2 自动轮播线程发生异常

ViewPager2 自动轮播线程发生异常





http://img1.sycdn.imooc.com//climg/5e3263d0094dd5a318830941.jpg

老师,我是跟着课程 综合案例:慕淘旅游--》指示器:自动滑动版  做的,和课程里没区别呀,课程里的线程就能运行修改UI?

我的代码:

package com.example.mydemo.fragment;

import android.app.Activity;
import android.content.Context;
import android.net.Uri;
import android.os.Bundle;

import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.RecyclerView;
import androidx.viewpager2.widget.ViewPager2;

import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.SimpleAdapter;

import com.example.mydemo.R;
import com.example.mydemo.util.DataUtil;

import java.io.ObjectInputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


public class IndexFragment extends Fragment {
   private ViewPager2 pagers;
   private LinearLayout pointers;
   private int index = 1;//用于保存一个数字,控制ViewPager的显示页数
   private GridView grids;
   private List<Map<String,Object>> data=new ArrayList<>();

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

       pagers = view.findViewById(R.id.pagers);
       pointers = view.findViewById(R.id.pointers);
       grids=view.findViewById(R.id.grids);

       setViewPager();
       setGridView();

       return view;
   }

   private void setGridView() {
       for(int i=0;i<DataUtil.index_menu_imgs.length;i++){
           Map<String,Object> map=new HashMap<>();
           map.put("img",DataUtil.index_menu_imgs[i]);
           map.put("txt",DataUtil.index_menu_txts[i]);
           data.add(map);
       }
       String[] from={"img","txt"};
       int[] to={R.id.img,R.id.txt};

       SimpleAdapter adapter=new SimpleAdapter(getContext(),data,R.layout.index_menu_item,from,to);
       grids.setAdapter(adapter);
   }

   private void setViewPager() {
       RecyclerView.Adapter adapter = new RecyclerView.Adapter() {
           //用于获取盛放图片的控件的ViewHolder对象
           @NonNull
           @Override
           public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
               View v = LayoutInflater.from(getContext()).inflate(R.layout.adv_item, parent, false);
               return new ViewHolder(v);
           }

           //为ViewHolder对象中的控件设置显示效果
           @Override
           public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
               ViewHolder vh = (ViewHolder) holder;
               vh.v.setBackgroundResource(DataUtil.adv_imgs[position % 4]);

           }

           //设置pager的数量
           @Override
           public int getItemCount() {
               return Integer.MAX_VALUE;
           }
       };
       pagers.setAdapter(adapter);

       pagers.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
           @Override
           public void onPageSelected(int position) {
               super.onPageSelected(position);

               for (int i = 0; i < pointers.getChildCount(); i++) {
                   ImageView img = (ImageView) pointers.getChildAt(i);
                   img.setImageResource(R.drawable.dot_unselected);
               }
               ((ImageView) pointers.getChildAt(position % 4)).setImageResource(R.drawable.dot_selected);
           }
       })  ;


       //开启一个线程,控制每3秒切换一个广告
       new Thread() {
           @Override
           public void run() {
               super.run();
               while (true) {
                   try {
                       Thread.sleep(3000);
                   } catch (InterruptedException e) {
                       e.printStackTrace();
                   }
                   pagers.setCurrentItem(index);
                   index++;
               }
           }
       }.start();

   }

   class ViewHolder extends RecyclerView.ViewHolder {
       public View v;

       public ViewHolder(@NonNull View itemView) {
           super(itemView);
           v = itemView;
       }
   }

}

log异常报告:

2020-01-30 13:00:55.546 3551-3657/com.example.mydemo E/AndroidRuntime: FATAL EXCEPTION: Thread-3
    Process: com.example.mydemo, PID: 3551
    android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
        at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:6855)
        at android.view.ViewRootImpl.invalidateChildInParent(ViewRootImpl.java:1075)
        at android.view.ViewGroup.invalidateChild(ViewGroup.java:5242)
        at android.view.View.invalidateInternal(View.java:13574)
        at android.view.View.invalidate(View.java:13538)
        at android.view.View.invalidate(View.java:13522)
        at android.widget.ImageView.setImageDrawable(ImageView.java:514)
        at androidx.appcompat.widget.AppCompatImageView.setImageDrawable(AppCompatImageView.java:99)
        at androidx.appcompat.widget.AppCompatImageHelper.setImageResource(AppCompatImageHelper.java:90)
        at androidx.appcompat.widget.AppCompatImageView.setImageResource(AppCompatImageView.java:93)
        at com.example.mydemo.fragment.IndexFragment$2.onPageSelected(IndexFragment.java:100)
        at androidx.viewpager2.widget.CompositeOnPageChangeCallback.onPageSelected(CompositeOnPageChangeCallback.java:73)
        at androidx.viewpager2.widget.CompositeOnPageChangeCallback.onPageSelected(CompositeOnPageChangeCallback.java:73)
        at androidx.viewpager2.widget.ScrollEventAdapter.dispatchSelected(ScrollEventAdapter.java:331)
        at androidx.viewpager2.widget.ScrollEventAdapter.notifyProgrammaticScroll(ScrollEventAdapter.java:266)
        at androidx.viewpager2.widget.ViewPager2.setCurrentItem(ViewPager2.java:449)
        at androidx.viewpager2.widget.ViewPager2.setCurrentItem(ViewPager2.java:412)
        at com.example.mydemo.fragment.IndexFragment$3.run(IndexFragment.java:118)

正在回答 回答被采纳积分+1

登陆购买课程后可参与讨论,去登陆

3回答
皮皮来了昂 2020-02-02 22:23:24

兄第,我和你一样的错误,你那里像我这样改就好使了。我在网上看到的用handle(android.os.Handler
)类可以让子线程实现更新ui,具体解释可以参考这个:https://www.cnblogs.com/xiaoerlang90/p/4159933.html

http://img1.sycdn.imooc.com//climg/5e36da320980d99f11770801.jpg

  • Handler,少打了一个r
    2020-02-02 22:24:15
  • 嗯,这是常用方式,不过Handler具体用法,同学可以在第二阶段学习到。祝:学习愉快
    2020-02-03 09:40:00
好帮手慕雪 2020-01-31 15:44:24

是指你的设备,也就是说你的手机版本。或者你也可以把.setCurrentItem() 这行代码外面增加以下

http://img1.sycdn.imooc.com//climg/5e33da1309ab9bc303910173.jpg

原因是,在原来的版本中ViewPager2是不能在子线程更改UI的,所以要把它移动到主线程中去运行它。至于都是什么不能在子线程中更新,一般的UI都是不可以的,除了进度条,ViewPager2也是后来才能的。这块内容会在下个阶段学习到它。

  • 提问者 黄启年 #1
    我用的安卓虚拟机Pixel 2 API 24 一般用什么版本的好呢
    2020-01-31 16:06:20
  • 好帮手慕雪 回复 提问者 黄启年 #2
    最新版本29是没有问题的。为了版本的兼容,还是加上面的最保险
    2020-01-31 16:07:22
  • 提问者 黄启年 #3
    new Thread() { @Override public void run() { super.run(); while (true) { try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } runOnUiThread(new Runnable(){ @Override public void run() { pagers.setCurrentItem(index); } }); index++; } } }.start(); 老师这样改吗?runOnUiThread()这个是要用谁引用吗?怎么用的
    2020-01-31 16:09:58
提问者 黄启年 2020-01-30 15:25:01

老师,我用课程源码运行一遍也是自动轮播线程那的报同样的异常

  • 你设备用的是什么版本,用个高点的版本。ViewPager2 是在29后才有的。所以系统向下兼容,不一定每个方法都能兼容的那么好
    2020-01-30 16:43:56
  • 提问者 黄启年 回复 好帮手慕雪 #2
    我的android studio3.5,然后build.gradle是这样的: apply plugin: 'com.android.application' android { compileSdkVersion 29 buildToolsVersion "29.0.2" defaultConfig { applicationId "com.example.mydemo" minSdkVersion 15 targetSdkVersion 29 versionCode 1 versionName "1.0" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } } dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation 'androidx.appcompat:appcompat:1.0.2' implementation 'androidx.constraintlayout:constraintlayout:1.1.3' implementation 'androidx.legacy:legacy-support-v4:1.0.0' implementation 'androidx.viewpager2:viewpager2:1.0.0-alpha02' testImplementation 'junit:junit:4.12' androidTestImplementation 'androidx.test.ext:junit:1.1.0' androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1' } 我的版本挺gao的呀
    2020-01-30 17:08:24
问题已解决,确定采纳
还有疑问,暂不采纳

恭喜解决一个难题,获得1积分~

来为老师/同学的回答评分吧

0 星
请稍等 ...
意见反馈 帮助中心 APP下载
官方微信

在线咨询

领取优惠

免费试听

领取大纲

扫描二维码,添加
你的专属老师