匿名クラスとラムダと時々弱参照

by orekyuu 0 Comments

今Javaビーム工房の作り直しをしていて、その中でWeakReferenceを使ったObserverパターンを書いた。

やりたいことは大体こんな感じ。

これは参照されなくなった時にGCされるとリスナが呼び出されなくなるって感じの挙動になる。
実行するとAAAだけ出力されてGCされた後のBBBは出力されない。

これ使えばリスナの解除を忘れてた時もメモリリークしにくくなると思ったけど思った通りに動作しなかった。
さっきのコードでは問題なく動いているけど、ラムダでaddListenerをするとGCしても参照が消えない。
そこで書いてみたのがこのコード

匿名クラスを使用しているときは問題なく消えてるけど、ラムダを使った時は残ったままだし消えない。
匿名クラスとラムダが違うというのは聞いたことあったけど、こんなところで違いが出てくるとは思わなかった。原因はなんなんだろう・・・?

Javaビーム工房で学んだチーム開発の難しさ

by orekyuu 0 Comments

同じ学校のメンバーに声をかけて一緒に作っていたTwitterクライアントのα版がようやく出せた。
10月1日から始めたので大体3ヶ月くらい。まぁバグとか結構あったり未実装の部分もあるけどまぁ満足の行くところまでできたと思う。
チーム開発の経験はあまりないけど、3ヶ月ほどやってみて課題とかをまとめてみたいと思う。

今回のプロジェクトはgitとgradleを使った。
プロジェクト構成としては、JavaBeamStudioにJavaBeamStudioAPIとJavaBeamStudioAppの二つのサブプロジェクトがあるだけ。

プロジェクト開始時にgradleラッパーをプロジェクトに入れておくと、チームメンバーの環境が整えやすくて非常に良かった。
各自作業がしやすいようにEclipseかIntelliJの好きな方を使ってくれというスタンスだったが、今になってすごく後悔している。
というのも、コードのフォーマットがばらばらでタブでインデントする人が居たりしてひどいことになった。
最終的にαビルド前に全体にフォーマットかけることにしたが、rebaseするときに「あっ・・・(察し」となるのは目に見えている。

やっぱりIDEは統一させておいたほうがいいのかもしれない。
フォーマットの問題が解決すれば各自使いやすいものでいいと思うけど・・・(各自のモチベーションも上がるだろうし。

開発の流れは、週1回のスカイプ会議で各メンバーにタスクを割り振り、release-1.0.0から新規ブランチを作って完成すればプルリクエストを作成してマージする方法をとっているが、あまり効果が実感できていない。実際バグが大量に出ている。
もう少し厳しいチェックを通す方法を考えたいと思う。

JavatterAdventCalendarその5

by orekyuu 0 Comments

JavatterAdventCalendarの16日目の記事です。

今回はFXMLを使ってGUIの作成をします。
JavaFXではSwingのようにソースコードでレイアウトを作るだけでなく、FXMLと呼ばれるXMLのような言語でレイアウトを作成することが可能です。
今回はFXMLを使ってGUIを作成し、ボタンをクリックすることで新規ウィンドウでFXMLのGUIを表示してみます。

まずはFXMLを作成します。

<?xml version="1.0" encoding="UTF-8"?>

<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.paint.*?>

<BorderPane id="BorderPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2">
  <center>
    <Label text="WindowTest" />
  </center>
</BorderPane>

BorderPaneのCenterにLabelを配置しているだけです。
直接手書きをしてもいいですが、SceneBuilderを使うことにより簡単に作成することが可能です。
SceneBuilder

SceneBuilderはこちらからDLできます。

次にこれを読み込みます。
JavatterFxmlLoader#load(Class,String)を使って読み込むことが出来ます。
第一引数にはFXMLと同じパッケージに属しているClassを渡し、第二引数にはFXMLのファイル名を渡します。

あとはWindowを開いてloadで戻ってきたParentを設定して完成です。

try {
	Parent p=JavatterFxmlLoader.load(getClass(), "TestWindow.fxml");//ロード
	Scene scene=new Scene(p);//シーンを作成
	Stage stage=new Stage();//新しいステージ(Window)を作成する
	stage.setScene(scene);//ステージにシーンを設定」
	stage.centerOnScreen();//ステージを画面中央へ
	stage.setTitle("TestWindow");//タイトルを設定
	stage.show();//表示
} catch (IOException e) {
	e.printStackTrace();
}

これで読み込み完了です。あとはボタンをクリックした時この処理をするようにしましょう。

@EventHandler
	public void onCreateTweetobject(final EventInitializeTweetobject event){
		MenuItem item=new MenuItem("Window");
		event.getController().addMenuItem(item);
		item.setOnAction(new javafx.event.EventHandler<ActionEvent>() {
			@Override
			public void handle(ActionEvent arg0) {
				try {
					Parent p=JavatterFxmlLoader.load(getClass(), "TestWindow.fxml");//ロード
					Scene scene=new Scene(p);//シーンを作成
					Stage stage=new Stage();//新しいステージ(Window)を作成する
					stage.setScene(scene);//ステージにシーンを設定」
					stage.centerOnScreen();//ステージを画面中央へ
					stage.setTitle("TestWindow");//タイトルを設定
					stage.show();//表示
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		});
	}

次回はGUIを操作するコントローラーの解説をする予定です。お疲れ様でした。

JavatterAdventCalendarその4

by orekyuu 0 Comments

JavatterAdventCalendarの14日目の記事です。

今回はイベントの自作をする方法を解説します。
今回はMyPluginInitEventを自作してPlugin.Initでイベントを発生させます。

イベントの作成はとても簡単です。
com.github.orekyuu.javatterfx.event.Eventインターフェイスを実装させるだけです。
このインターフェイスはマーカーインターフェイスになっていてメソッドをオーバーライドする必要はありません。

package com.orekyuu.plugin.test.events;

import com.github.orekyuu.javatterfx.event.Event;

public class MyPluinInitEvent implements Event{

}

次にこのイベントを通知します。
通知はEventManager#eventFire(Event)を使って行います。
適当なタイミングでこのメソッドを呼び出し、引数には起こしたいイベントのインスタンスを渡します。

EventManager.INSTANCE.eventFire(new MyPluinInitEvent());

これでイベントの自作はできました。
イベントで値を渡したい場合はEventを実装したクラスに変数を持たせておき、インスタンス作成時に適当な値を設定してからeventFireをすることで可能です。

お疲れ様でした。

JavaFXでTwitterクライアント作ってみた。

by orekyuu 0 Comments

この記事はJavaFX Advent Calendarの12日目です。
前回は@kisさんのJavaFXでSeleniumっぽいものを作るでした。

・JavaFXでTwitterクライアント作ってみた
今年の春頃にSwingを使ってJavatterというTwitterクライアントをすでに作っていて、完成した後にJavaFXの存在を知ってJavaFXで新しく作りなおすことにしました。

こちらがSwingで作ったクライアントです。
JavatterSwing

そしてJavaFXで作りなおしたのがこちらです。
JavatterFX

JavaFX、結構シャレオツだと感じました。Swingがださすぎたのか?

・JavaFXの話
JavaFXでブラウザを開く方法を紹介します。

今までは

Desktop.getDesktop().browse(new URL("https://www.google.co.jp/").toURI());

のようにDesktopクラスを使ってブラウザを開いていました。

JavaFXを使ってブラウザを立ち上げるにはHostServices#showDocument(String)を使います。

Application app;
app.getHostServices().showDocument("https://www.google.co.jp/");

・おわり
今回紹介したTwitterクライアントのソースはこちらで見れます。

Swingなんてなかったんや!JavaFXすごい!ということで私の記事はおしまいです。
ありがとうございました!

JavatterAdventCalendarその2

by orekyuu 0 Comments

JavatterAdventCalendarの9日目の記事です。

今回はJavatterのイベントシステムについて解説します。
今回はデモとしてユーザーストリームを取得して、「JavaJava」という発言に対して「@ユーザー名 じゃばっ」とリプライを送るプラグインを作ってみます。

JavatterFX本体はここからダウンロードするかGithubからクローンして自分でビルドしてください。

まずは前回と同じようにロードされた時に動くPluginMainクラスを作りましょう。
Plugin.Initができれば、次にイベントを受け取るリスナクラスを作成します。
今回はMyEventListenerというクラス名にしておきます。
MyEventListenerにはcom.github.orekyuu.javatterfx.event.Listenerを実装する必要があります。

次にイベントを受け取るメソッドを作ります。
今回はユーザーストリームから新しいStatusが来た時のイベントを受け取るメソッドを作ります。

@EventHandler
public void onStatus(EventStatus event){
	
}

メソッドの引数に受け取りたいイベントのクラスを設定し、EventHandlerアノテーションをつけることで引数のイベントに応じて適切なタイミングで呼び出されます。
メソッドの名前は自分の好きな名前で構いません。
あとはツイートの内容がJavaJavaであるかどうかを比較してTweetDispenser#tweetメソッドでつぶやけばリスナは完成です。

最後にこのリスナを登録します。
PluginMainのPlugin.Initが付加されたメソッドで登録しましょう。
EventManager#addEventListener(Listener)を使って登録します。

これで完成です。起動して動作を確認してみましょう。
ソースコードをここに書いておきます。
PluginMain

package com.github.orekyuu.plugin;

import com.github.orekyuu.javatterfx.event.EventManager;
import orekyuu.plugin.loader.Plugin;

@Plugin(name = "じゃばっプラグイン", version = "1.0")
public class PluginMain {

	@Plugin.Init
	public void init(){
		EventManager.INSTANCE.addEventListener(new MyEventListener());
	}
}

MyEventListener

package com.github.orekyuu.plugin;

import com.github.orekyuu.javatterfx.event.EventHandler;
import com.github.orekyuu.javatterfx.event.Listener;
import com.github.orekyuu.javatterfx.event.stream.EventStatus;
import com.github.orekyuu.javatterfx.util.TweetDispenser;

public class MyEventListener implements Listener{

	@EventHandler
	public void onStatus(EventStatus event){
		if(event.getTweetText().equals("JavaJava")){
			TweetDispenser.tweet("@"+event.getAccount()+" じゃばっ");
		}
	}
}

JavatterAdventCalendarその1

by orekyuu 0 Comments

JavatterAdventCalendar4日目です。
自分の記事ではSwingで作られているJavatterβの方ではなく、現在開発中のJavatterFXについて書こうと思います。

1回目はJavatterFXのプラグインの作成方法です。
今回は起動直後にHelloJavatterFXと呟くプラグインを作成してみます。

開発に必要になるので、本体を準備しましょう。
ここからダウンロードするかGithubからクローンして自分でビルドしてください。

まずはロードされた時に呼ばれるクラスを作成します。
今回はcom.github.orekyuu.plugin.PluginMainクラスを作成。
そしてorekyuu.plugin.loader.Pluginをインポートし、PluginアノテーションをPluginMainクラスに付けます。
nameにはプラグインの名前を文字列で与えます。
versionにはバージョンを文字列で与えます。

package com.github.orekyuu.plugin;

import orekyuu.plugin.loader.Plugin;

@Plugin(name = "プラグイン名", version = "1.0")
public class PluginMain {

}

次にロード時に呼ばれるメソッドを定義します。
@Plugin.Initアノテーションが付加されたメソッドはプラグインがロードされた時に実行されます。
メソッド名は好きな名前で構いません。

@Plugin.Init
public void init(){

}

今回はロードされた時につぶやきたいので、initの段階でつぶやくことにします。
ツイートをするにはcom.orekyuu.javatterfx.util.TweetDispenserを使用します
TweetDispenserのtweetメソッドはツイートをQueueに加え、別のスレッドで順番に処理されます。
JavatterβのTwitterUtilのtweetメソッドでは完全に別のスレッドでツイート処理が行われていたため、ツイートの順番は保証されていませんでしたが、TweetDispenserは呟く順番が保証されます。

ソースコードが完成しました。一応コードを載せておきます。

package com.github.orekyuu.plugin;

import orekyuu.plugin.loader.Plugin;

import com.github.orekyuu.javatterfx.util.TweetDispenser;

@Plugin(name = "プラグイン名", version = "1.0")
public class PluginMain {

	@Plugin.Init
	public void init(){
		TweetDispenser.tweet("Hello!JavatterFX");
	}
}

プラグインの配布方法はJarファイルとして出力するだけです。JavatterFXはロードされたクラスの中からPluginアノテーションの付加されたクラスを検索するのでマニフェストファイルの編集は必要ありません。
実際に実行してみてHello!JavatterPluginとツイートできていれば完成です。お疲れ様でした。

ListViewつらい。

by orekyuu 0 Comments

JavatterFX進捗だめです。
スクロールするだけでメモリの使用量がガンガン増えていく・・・どこに参照が残っているのか・・・
というかスクロールするだけで新しくインスタンス作るのやめてくれ!頼む!

ユーザーウィンドウできました。

by orekyuu 0 Comments

JavatterFXのユーザーウィンドウ出来ました。
UserInfo
こんなかんじのウィンドウです。
切り替えの時は上のToggleボタンを使って移動します。
折角なので、切替時のアニメーションをやってみました。イメージ的にはスマホとかのスワイプみたいな感じです。
anim

Swingと比べるとアニメーションがすごく楽でした。(そもそもSwingでアニメーションさせてなかったけど)

今回使った単純な移動のほうほうですが、TranslateTransitionというクラスを使ってやっています。

int MOVETIME=600;//アニメーションする時間
TranslateTransition trans=new TranslateTransition(Duration.millis(MOVETIME));//600ミリ秒アニメーションする
trans.setNode(node);//アニメーションさせたいNodeを渡す
trans.setFromX(0);//アニメーション開始地点を0に
trans.setToX(100);//アニメーション終了地点を100に
trans.playFromStart();//アニメーション開始

コード見れば解説必要なさそうな感じですが、nodeが0から100まで動くよって感じのコードです。
簡単ですよね!

ちなみにZ軸も扱えたりするので動きに幅が出て面白いと思います。これだけでもいろいろできるので、ぜひJavaFXで遊んでみてください

ちなみに先日関ジャバに初参加してきたのですが、スピーカーの方が映していた資料がパワポだと思っていたらJavaFXで作ったものだったみたいです。
JavaFXすごすぎ。というよりパワポ使わずにJavaFXでやろうという発想もやばい…