3

私はここに誰かが助けてくれることを願っています。私はObserver Design Pattern、Threading、そして私がやっているプロジェクトにどうやって両方を使うことができるかを考えています。Java - このようにObserver Patternとスレッドを使用することは可能ですか?

私は現在、両方をMedia Playerで実装する必要があります。私はJava FXを使用してビルドしています。

私は自分のディレクトリ内のファイルのによりgetNames機能によって移入(私のリストビューを更新するために、それらの両方を使用する必要があります。私は、GUI上ですぐに反映させるために曲の私のフォルダへの変更を必要とする。

がそれです可能であれば、実行中のスレッドが常にgetNames関数を呼び出して(items変数を返す)、items変数に変更があった場合、Observerパターンを使用してGUIクラスにそのリストを更新することができます。

私は、スレッドが絶えず機能にぶつかっている可能性があることを知っていますが、Observerパターンを使用して項目が変更されたかどうかを通知できるかどうかについてのアドバイスが必要です。

私はまだこれを実装する方法を理解しようとしているので、表示するコードはありません。

アイデア?

何かアドバイスをありがとうございます。感謝:)

UPDATEかなり長い時間が経過した後

、スレッドとオブザーバpattermでの作業、これを手に入れました。 WatchServiceは必要ありませんでした。変更メソッドのチェックを常に呼び出すためにスレッドを使用しました。その後メソッドが戻ってきた場合、ObserverがGUIを更新するために起動しました。

+2

あなたはこれができない可能性がありますと思わせる何か? – John3136

+2

これは可能ですが、面倒でエラーが発生する可能性があります。 'SwingWorker'がスレッド間で共有されるデータへのアクセスを同期させることを考慮してください。 – trashgod

+0

Observorがファイルの変更を検出してlistViewを変更する方法について、本当に苦労しています。 –

答えて

0

このパターンを使用するために、その可能性は、ファイルの更新のためにフォルダに時計を維持するためのスレッドを実行すると、例えば、あなたのスレッド を実行するには、このスレッド安全な使用のEventQueueのを確認する必要があり java.awt.EventQueue.invokeLaterまたはinvokeAndWaitの

変更がスレッドによって検出されると、その後、あなたのオブザーバーパターンはGUI

希望を更新するこのことができます!

+0

ありがとうございました!ほとんどそれは働いている! –

0

この(IMO)への最善のアプローチは、次のようになります。

  1. WatchService上のこのOracleチュートリアルを考えてみましょう。
  2. JavaFXを使用しているときは、JavaFX Taskのチュートリアルの「時計サービスを実装するために必要な基本ステップ」をラップしてください。
  3. おそらく、ウォッチ・サービスによって検出された変更をビューにフィードバックするために、タスクjavadoc「部分結果を返すタスク」のパターンに従ってください。

「残念ながら私たちの講師はWatchServiceを使用できません」とメモしていますので、FileSystemのアクティブな投票である以下のサンプルコードのような方法を使用できます。 WatchServiceの使用は、JDK実装の内部では、OS提供のファイル監視サービスを利用できるため、間違いなく推奨されています。それらのOSサービスは、ファイル変更イベントの通知を提供することができるので、Javaコードは変更をファイルシステムに積極的にポーリングする必要がありません。それにもかかわらず、次の非効率的な仕事は、この場合に仕事をするのに十分でしょう...

ファイルシステムをポーリングするスレッドにJavaFXタスクを生成し、ファイルシステム上のファイルと一致するように、観察可能リストを変更してListViewをバックアップします。リストの変更はPlatform.runLaterコール内で実行され、アクティブなシーングラフがJavaFXアプリケーションスレッドから変更されないように、リストビューをサポートするリストの変更がJavaFXアプリケーションスレッド上で確実に行われるようにします。

sample output

import javafx.application.*; 
import javafx.collections.*; 
import javafx.collections.transformation.SortedList; 
import javafx.concurrent.Task; 
import javafx.scene.Scene; 
import javafx.scene.control.*; 
import javafx.stage.Stage; 

import java.io.File; 
import java.nio.file.*; 
import java.util.Arrays; 
import java.util.Comparator; 

public class FileWatcher extends Application { 

    private static final Path WATCH_DIR = Paths.get(System.getProperty("user.dir")); 

    public static void main(String[] args) { 
     launch(args); 
    } 

    @Override 
    public void start(Stage stage) { 
     ObservableList<File> songFileList = FXCollections.observableArrayList(); 
     SortedList<File> sortedSongFileList = new SortedList<>(
       songFileList, 
       Comparator.comparing(File::getName) 
     ); 

     ListView<File> songListView = new ListView<>(); 
     songListView.setItems(sortedSongFileList); 
     songListView.setCellFactory(param -> new ListCell<File>() { 
      @Override 
      protected void updateItem(File item, boolean empty) { 
       super.updateItem(item, empty); 

       if (item == null || empty) { 
        setText(null); 
        return; 
       } 

       setText(item.getName()); 
      } 
     }); 

     SongWatcher watcher = new SongWatcher(
       WATCH_DIR, songFileList 
     ); 
     Thread watcherThread = new Thread(watcher, "song-watcher"); 
     watcherThread.setDaemon(true); 
     watcherThread.start(); 

     Scene scene = new Scene(songListView); 
     stage.setScene(scene); 
     stage.show(); 
    } 

    class SongWatcher extends Task<Void> { 
     private static final String SONG_EXTENSION = "mp3"; 
     private static final long POLL_INTERVAL_MILLIS = 200; 

     private final Path directory; 
     private final ObservableList<File> songFiles; 

     SongWatcher(Path directory, ObservableList<File> songFiles) { 
      this.directory = directory; 
      this.songFiles = songFiles; 
     } 

     @Override 
     protected Void call() { 
      System.out.println("Started watching " + directory + " for song file changes."); 

      while (!isCancelled()) { 
       try { 
        Thread.sleep(POLL_INTERVAL_MILLIS); 
       } catch (InterruptedException e) { 
        if (isCancelled()) { 
         break; 
        } 

        Thread.currentThread().interrupt(); 
       } 

       try { 
        if (!Files.isDirectory(directory)) { 
         throw new Exception("Watched directory " + directory + " is not a directory."); 
        } 

        File[] foundFiles = 
          directory 
            .toFile() 
            .listFiles(
              (dir, name) -> name.endsWith(SONG_EXTENSION) 
            ); 

        if (foundFiles == null) { 
         throw new Exception("Watched directory " + directory + " find files returned null (this is not expected)."); 
        } 

        Platform.runLater(() -> { 
         // remove files from the song list which are no longer on the disk. 
         songFiles.removeIf(checkedFile -> 
           Arrays.binarySearch(foundFiles, checkedFile) < 0 
         ); 

         // add any files which are on the disk which are not in the song list. 
         for (File file: foundFiles) { 
          if (!songFiles.contains(file)) { 
           songFiles.add(file); 
          } 
         } 
        }); 
       } catch (Exception e) { 
        e.printStackTrace(); 
       } 
      } 

      return null; 
     } 

     @Override 
     protected void succeeded() { 
      System.out.println("Stopped watching " + directory + " for song file changes."); 
     } 

     @Override 
     protected void cancelled() { 
      System.out.println("Cancelled watching " + directory + " for song file changes."); 
     } 

     @Override 
     protected void failed() { 
      System.out.println("Failed watching " + directory + " for song file changes."); 
      if (getException() != null) { 
       getException().printStackTrace(); 
      } 
     } 
    } 
} 
+0

詳細な回答をいただきありがとうございます。本当にありがとうございます。 スレッドとオブザーバーがほぼ協力しています。 –

関連する問題