使用接口 + ExecutorService 问题的动态 UI 进度更新

Dynamic UI Progress Updates using Interface + ExecutorService Issue

所以我有一个音乐应用程序。每次歌曲更改时,我都试图用媒体播放器的进度(如当前时间、当前歌曲、专辑封面)更新 UI。我发现使用接口是 activity 和片段之间的一种神奇的通信方式,所以我在我的 MusicManger class 中实现了一个接口。我的代码将显示它是做什么的以及如何做的。

两个问题

1) 评论看下面,ExecutorService好像循环一圈就停止了。 catch 块中没有错误(这就是我用 java 标记的原因)

2) 评论请看,所有 System.out 方法打印但 UI 不更新。我确实相信我从 mainThread 调用了该方法,因此它应该更新。

我将按逻辑顺序显示代码,在代码段前添加粗体标题以告诉您代码的基本概念。

将片段中的 UI 引用传递给 MusicManager class,片段下面的代码 class

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

    // Set the adapter

    TextView musicManagerSongName, musicManagerCurrent, musicManagerTotal;
    ProgressBar musicManagerProgress;
    ImageView musicManagerImageView;
    mListView = (AbsListView) view.findViewById(R.id.slist);
    musicManagerSongName = (TextView)view.findViewById(R.id.textView12);
    musicManagerCurrent = (TextView)view.findViewById(R.id.textView10);
    musicManagerTotal = (TextView)view.findViewById(R.id.textView11);
    musicManagerProgress = (ProgressBar)view.findViewById(R.id.progressBar);
    musicManagerImageView = (ImageView)view.findViewById(R.id.imageView2);

    MainActivity.mediaPlayer.passUIReferences(musicManagerSongName, musicManagerCurrent, musicManagerTotal, musicManagerProgress, musicManagerImageView, view);

// line above is a method within MusicManager that takes the references will show code next!

    ImageButton playbutton = (ImageButton)view.findViewById(R.id.playbuttonbar);
    ImageButton nextButton = (ImageButton)view.findViewById(R.id.nextbuttonbar);
    ImageButton backButton = (ImageButton)view.findViewById(R.id.backbuttonbar);
    ImageButton toggleButton = (ImageButton)view.findViewById(R.id.shufflebuttonbar);
    ImageButton pausebutton = (ImageButton)view.findViewById(R.id.pausebuttonbar);
    playbutton.setBackgroundResource(R.drawable.playbuttonbar);
    playbutton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            try {
                MainActivity.mediaPlayer.stateChange(1);
            }catch(Exception e) {

            }
        }
    });
    backButton.setBackgroundResource(R.drawable.backbutton1);
    nextButton.setBackgroundResource(R.drawable.nextbutton1);
    toggleButton.setBackgroundResource(R.drawable.shufflebuttonselected);
    pausebutton.setBackgroundResource(R.drawable.pausebutton1);
    pausebutton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            try {
                MainActivity.mediaPlayer.stateChange(0);
            } catch (Exception e){

            }
        }
    });
    mListView.setAdapter(mAdapter);
    ((MainActivity) mListener).restoreActionBar();

    return view;
}

如上文所述,位于 MusicManager class 中的代码采用引用并存储它们。还显示了 MusicManager class 的接口实现。执行器服务

public void passUIReferences(View... views) {
    this.uiElements = views;
}

 private ExecutorService executorService = Executors.newSingleThreadExecutor();
private MediaplayerUpdateInterface uiUpdateInterface;

public MediaPlayerManager(MediaplayerUpdateInterface inter) {
    this.player = new MediaPlayer();
    this.uiUpdateInterface = inter;

// The below line starts the single thread while loop for excutorservice and only loops and prints "this" once after I start one song then it never loops again
    executorService.submit(new Runnable() {
        @Override
        public void run() {
            while(true) {
                if (player.isPlaying() && uiElements != null) {
                    System.out.println("this");
                    uiUpdateInterface.updateUI(uiElements, 0);
                }
                try {
                    Thread.sleep(500);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    });
}

public interface MediaplayerUpdateInterface {
    public void updateUI(View[] views, int type);
}

最后一些来自 MainActivity class 的代码实际上应该更新 UI 请注意,两个 println 都按预期工作,但如上所述只有一次由于 executorservice 问题

  public static MediaPlayerManager mediaPlayer = new MediaPlayerManager(new MediaPlayerManager.MediaplayerUpdateInterface() {
    @Override
    public void updateUI(View[] views, int type) {
        System.out.println("check1 " + type);
        updateMediaplayerViews(views, type);
    }
});

private static void updateMediaplayerViews(View[] views, int type)
{
    switch(type) {
        case 0:
            System.out.println("that?");
            ((TextView)views[0]).setText(mediaPlayer.getCurrentSongInfo().getName().length() > 22? mediaPlayer.getCurrentSongInfo().getName().substring(0, 19)+"..." : mediaPlayer.getCurrentSongInfo().getName());
            break;
    }
    views[views.length - 1].invalidate();
}

视图数组如前所示!数组中的最后一个视图也显示为歌曲列表片段的主视图。

对于我尝试调试它的所有代码,我深表歉意,正如您从我的 println 中看到的那样,我不知道这里发生了什么。

好的,所以我需要在以下代码中发现一个错误:

private static void updateMediaplayerViews(View[] views, int type)
{
switch(type) {
    case 0:
        System.out.println("that?");
        ((TextView)views[0]).setText(mediaPlayer.getCurrentSongInfo().getName().length() > 22? mediaPlayer.getCurrentSongInfo().getName().substring(0, 19)+"..." : mediaPlayer.getCurrentSongInfo().getName());
        break;
}
views[views.length - 1].invalidate();
}

问题是我试图从另一个线程更改视图,而不是创建它的线程。解决它是相当漫长和痛苦的,但基本上我让它成为非静态的使用更多的接口然后使用著名的

Mainactivity.runOnUiThread(new Runnable(....));