(Android & Java) Lombokでざっくりシャローコピー

伏見です。

Lombokとは、JavaでGetter,Setter,コンストラクタなどを自動生成していい感じに隠蔽してくれるツールです。
様々なアノテーションを使って表現します。
Lombok 使い方メモ

現在所属しているチームではモバイルアプリ開発を行っています。
Swift,Web,AndroidのAPIのIOやビジネスロジックの共通の大元をまずTypeScriptで書いており、そこからSwiftやJavaのデータ定義用コードを自動生成して各自で使っています。

Typescriptでデータ用モデルを定義するとき、ゲッターセッターだのまず書いていません。
Androidでの開発においても、最近はREST APIから渡ってくる情報や、アプリケーションのビジネスロジックを表現するようなシンプルなデータ用クラスを、js側で扱うpureなJSONとなるべく見た目的に等価にしておきたい気分でいます。

で、ゲッターセッター、コンストラクタの定義にLombokを使っているわけです。

で、本題ですが、このLombok、オブジェクトの浅いコピーにも使えます。
データ用クラスがCloneableを継承すれば当然Lombokなしでもシャローコピー(?)は実装できますが、前述の理由で余計なinterfaceやメソッドを定義してクラス内を汚したくないです。

(参考にしたリンク)

定義側


@AllArgsConstructor
@NoArgsConstructor
@Builder(toBuilder = true) //<-これ
public class PlayerStore {

    public int nowPlayOrder = 0;

}

使用側


            PlayerStore oldPlayerStore = allStore.playerStore;
            PlayerStore oldPlayerStore2 = allStore.playerStore;

            oldPlayerStore.nowPlayOrder = 20;
    
            Log.d("" , oldPlayerStore2.nowPlayOrder+""); //20
            Log.d("" , allStore.playerStore.nowPlayOrder + ""); //20

            allStore.playerStore = oldPlayerStore.toBuilder().build();
            oldPlayerStore.nowPlayOrder = 120;
   
            Log.d("" , oldPlayerStore2.nowPlayOrder+""); //120
            Log.d("" , allStore.playerStore.nowPlayOrder + ""); //20



結果は以上のような感じになります。

便利。
Android用オレオレRedux実装のReducerにあたる部分で使う予定ですが、他に使う場面あるかな…。

Read More

Android TextViewのmarqueeの挙動

三年目のfushimiです。

今回はAndroidの開発で地味にハマったとこをメモ。

 

世の中にはmarqueeエフェクトなるものがあります。HTMLでいうこれなんですが。↙︎

vr

( http://www.mbs1179.com/ さんから)

要するに文字が1行に収まりきらない時に文字を流すエフェクトです。

Androidのアプリ開発でこれを使う機会がありまして、妙な挙動があったのでメモります。

 

デフォルトのTextViewにはmarquee設定用の属性が一応あります。

(こんなの)


<TextView
 android:ellipsize="marquee"
 android:focusable="true"
 android:focusableInTouchMode="true"
 android:singleLine="true"
 android:marqueeRepeatLimit="marquee_forever"
 android:textColor="@color/playerText"
 android:id="@+id/song_title"
 android:text="@{nowSong.title}"
 android:textStyle="bold"
 android:textSize="20dp"
 android:layout_centerHorizontal="true"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content" />

       

しかしこのTextView、focusが当たってる時にしか動作しません。それだけならまだいいのですが、
他のTextViewにsetTextを叩くと、そちらにfocusが移り、marqueeのアニメーションがリセットされてしまいます。カクカク。
もちろん複数のTetViewにmarqueeを設定することもできません。

いろんな方法を試した方がおられるようですが、こちらにシンプルな解決法がありました。

どうやら同じViewGroup内に他のTextがなければOKなようです。そこで、TextViewを一段階他のレイアウトでラップします。


 <LinearLayout 
android:layout_width="wrap_content" 
android:layout_height="wrap_content">
 <TextView
 android:ellipsize="marquee"
 android:focusable="true"
 android:focusableInTouchMode="true"
 android:singleLine="true"
 android:marqueeRepeatLimit="marquee_forever"
 android:scrollHorizontally="true"
 android:duplicateParentState="true"
 android:layout_margin="16dp"
 android:id="@+id/artist_name"
 android:textColor="@color/playerText"
 android:layout_below="@+id/song_title"
 android:text="@{nowSong.artist_name}"
 android:layout_centerHorizontal="true"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content" />;
 
</LinearLayout>;

これで他のTextViewにsetTextしてfocusが変わっても、ひとまず正常動作するようになりました。

 

謎い。

Read More