33
LayoutAnalyzerでのGroovy利用について 2011/04/09 @kimukou_26

Layout analyzerでのgroovyの利用について

Embed Size (px)

Citation preview

Page 1: Layout analyzerでのgroovyの利用について

LayoutAnalyzerでのGroovyの利用について

2011/04/09

@kimukou_26

Page 2: Layout analyzerでのgroovyの利用について

自己紹介Kimukou_26 といいます

関東でフリーのSEしています

主に参加している勉強会JGGUG ・・日本Grails/Groovy ユーザーグループ

#jggug

ATEC ・・Android テスト部#android_tec

あまり貢献できてません。すみません><

今回は #yapf には勉強しにきたつもりが。。何故か発表する事にw

Page 3: Layout analyzerでのgroovyの利用について

今回話す事になったきっかけ

Page 4: Layout analyzerでのgroovyの利用について
Page 5: Layout analyzerでのgroovyの利用について
Page 6: Layout analyzerでのgroovyの利用について

CategoryAA() / B()

では解析してみましょう使っているツールは?Layoutopt

日本語解説サイト http://goo.gl/QCMij

本家解説サイト http://goo.gl/7cdt7

どんなツール?レイアウト.xmlの最適度チェックツール

あくまでナビゲーションだけで変更はしないよ

どこでGroovyを使っているの? XMLの解析Rule(GroovyRule)

Use Category(クラスに機能を後付けする機能)

対象クラス、Clousre

useスコープ内だと対象クラスでCategoryAの

ルール(処理)が使えるイメージ

use(CategoryA){

}

Page 7: Layout analyzerでのgroovyの利用について

Groovyで実際使うとこんなイメージ

class ExcelCategory {

/** ファイルを読み込む */

static void readXls(File self, Closure yield){

//読込処理

/** ファイルを編集する */

static void editXls(File self, Closure yield){

//編集処理

use (ExcelCategory) {

new File('hogehoge.xls').readXls{ excelApp ->

// hogehoge.xlsに対する何かしらの処理 }

FileクラスにreadXls()

関数が追加されたイメージ

File self

の参照

Page 8: Layout analyzerでのgroovyの利用について

どんな構成になっているの?

ANDROID_HOME/tools/

layoutopt.bat

lib/layoutpot.jar

lib/uix.jar(LayoutAnalyzer , LayoutAnalysis )

lib/groovy-all-1.7.0.jar

com.android.layoutopt.cli.Main

LayoutAnalyzer analyzer = new LayoutAnalyzer()

LayoutAnalyzer

loadRules

Rule(Interface)

GroovyRule(implements Rule)

実際の構造はどんな感じ?

Page 9: Layout analyzerでのgroovyの利用について

処理の流れの抜粋

void main(String[] args)

static void analyzeFiles(File[] files)

LayoutAnalyzer analyzer = new LayoutAnalyzer();

static void analyze(LayoutAnalyzer analyzer, File file)

LayoutAnalysis analysis = analyzer.analyze(file);

com.android.layoutopt.cli.Main

Layoutopt.jar

uix.jar

com.android.layoutopt.uix.LayoutAnalyzer

LayoutAnalyzer()loadRules()

loadRule

Page 10: Layout analyzerでのgroovyの利用について

com.android.layoutopt.uix.rules.GroovyRule

import com.android.layoutopt.uix.LayoutAnalysis;import com.android.layoutopt.uix.groovy.LayoutAnalysisCategory;

import groovy.lang.*;import groovy.xml.dom.DOMCategory;import java.util.*;import org.codehaus.groovy.runtime.GroovyCategorySupport;import org.w3c.dom.Node;

void loadRules()ClassLoader parent = getClass().getClassLoader();GroovyClassLoader loader = new GroovyClassLoader(parent);GroovyShell shell = new GroovyShell(loader);

void loadRule(GroovyShell shell, String name, InputStream stream) {Script script = shell.parse(stream);this.mRules.add(new GroovyRule(name, script));

}

GroovyShellを

初期化

public void addRule(Rule rule) があるので外からRule追加は可能

かと

Page 11: Layout analyzerでのgroovyの利用について

public class GroovyRule implements Rule {private final String mName;private final Script mScript;private final Binding mBinding;private final Closure mClosure;private final List<Class> mCategories;

public GroovyRule(String name, Script script) {this.mName = name;this.mScript = script;this.mBinding = new Binding();this.mScript.setBinding(this.mBinding);

this.mClosure = new Closure(this) {public Object call() {

return GroovyRule.this.mScript.run();}

};

this.mCategories = new ArrayList();Collections.addAll(this.mCategories,

new Class[]{

DOMCategory.class,LayoutAnalysisCategory.class });

}

適応するCategoryクラス

を配列定義

実際の処理を行うClosure

Uix.jarRules/XX.rule

を読み込んだスクリプトファイルデータ

Page 12: Layout analyzerでのgroovyの利用について

Closure、Scriptのクラスのソース抜粋<参考package groovy.lang;

public abstract class Closure extends GroovyObjectSupport implements Cloneable,Runnable, Serializable {

public Closure(Object owner, Object thisObject) {

this.owner = owner;

this.delegate = owner;

this.thisObject = thisObject;

CachedClosureClass cachedClass =CachedClosureClass)ReflectionCache.getCachedClass(getClass());

this.parameterTypes = cachedClass.getParameterTypes();

this.maximumNumberOfParameters =cachedClass.getMaximumNumberOfParameters();

}

package groovy.lang;public abstract class Script extends GroovyObjectSupport{

private Binding binding;public abstract Object run();

}

Page 13: Layout analyzerでのgroovyの利用について

com.android.layoutopt.uix.rules.GroovyRule(続)

public class GroovyRule implements Rule {

~略~

public void run(LayoutAnalysis analysis, Node node) {this.mBinding.setVariable("analysis", analysis);this.mBinding.setVariable("node", node);GroovyCategorySupport.use(

this.mCategories, this.mClosure);}

}

•GroovyCategorySupport.use ってなに?•実行処理クラスを別のクラスに後付けする(use)方法です•http://d.hatena.ne.jp/fumokmm/20090117/1232209001

•下記の関数を後付けします

行番号を表示しているのはcom.android.layoutopt.uix.xml.XmlDocumentBuilder

で行っています

Page 14: Layout analyzerでのgroovyの利用について

uix.jar内のruleファイルにuse適応

している認識が正のようです

rules/XX.rule<= 実は

groovyファイル

Page 15: Layout analyzerでのgroovyの利用について

// Rule: UselessLayout

//

// Description: Checks whether current node can be removed.

//

// Conditions:

// - The node has children

// - The node does not have siblings

// - The node's parent is not a scroll view (horizontal or vertical)

// - The node does not have a background or its parent does not have a

// background or neither the node and its parent have a background

// - The parent is not a <merge/>

if (!node.isRoot() && !(node['..'].name() in ["ScrollView", "HorizontalScrollView"])&&

node['..']['*'].size() == 1 && node['*'].size() > 0 &&((node.'@android:background' ||

node['..'].'@android:background') || (!node.'@android:background' &&

!node['..'].'@android:background'))) {

analysis << "This ${node.name()} layout or its ${node['..'].name()} parent is " +

"${node['..'].'@android:id' ? "possibly useless" : "useless"}"

}

uix.jarの Rules/ UselessLayout.rule ファイル

com.android.layoutopt.uix.groovy.LayoutAnalysisCategory

public static LayoutAnalysis leftShift(

Page 16: Layout analyzerでのgroovyの利用について

public static int getStartLine(Node node)public static int getEndLine(Node node)

com.android.layoutopt.uix.groovy.LayoutAnalysisCategory

com.android.layoutopt.uix.LayoutAnalysispublic int getStartLine() {

return LayoutAnalysisCategory.getStartLine(this.mNode);}

public int getEndLine() {return LayoutAnalysisCategory.getEndLine(this.mNode);

}

com.android.layoutopt.uix.groovy.LayoutAnalysisCategorypublic static class Issue

内部Innerクラスで使っている

からあえて宣言書いていると思われ

Page 17: Layout analyzerでのgroovyの利用について

他のG系の技術を使ったコード

import groovy.lang.GString;public static LayoutAnalysis leftShift(

LayoutAnalysis analysis, GString description){analysis.addIssue(description.toString());return analysis;

}

•GString ・・String型のGroovy拡張クラスです•@fumokmm さん解説サイトhttp://d.hatena.ne.jp/fumokmm/20110323/

com.android.layoutopt.uix.groovy.LayoutAnalysisCategory

•Groovyコード上だと• int num=2• String aaa=“ほげほげ$num ${num/20}” と書けます• String bbb=‘まいう’

• シングルで囲むと普通のString型

計算式OK

Page 18: Layout analyzerでのgroovyの利用について

import groovy.xml.dom.DOMCategory;

public static List<Node> all(Element element) {NodeList list = DOMCategory.depthFirst(element);int count = list.getLength();List nodes = new ArrayList(count - 1);for (int i = 1; i < count; i++) {

nodes.add(list.item(i));}return nodes;

}

•DOMCategory ・・ DOM操作を簡単にするCategory定義クラス• XML読み(英語) http://goo.gl/SPG93• XML書き(英語) http://goo.gl/nPxqO•@nobusue さんサンプル

•https://gist.github.com/619066

com.android.layoutopt.uix.groovy.LayoutAnalysisCategory

Page 19: Layout analyzerでのgroovyの利用について

Groovyは何が美味しいの?

Javaは実行コンパイル面倒

スクリプトで実行したい!

Java実行スクリプトJRubyで書けるけど、Ruby文法で書き直すの嫌だよね

XXX.java=>XXX.groovyと拡張子変更だけで実行できると楽だよね GroovyConsoleだと拡張子Javaでも実行可能

groovyConsoleで多少の修正で動作可能配列記述 「}」 =>「]」 に修正

もっとシンプルに書こうよーJSみたいクロージャ等使って

Page 20: Layout analyzerでのgroovyの利用について

Groovyを学習するには@fumokmm さんGroovy基礎文法最速マスター

http://d.hatena.ne.jp/fumokmm/20100605/1275736594

Java使いをGroovyに引き込むサンプル集http://d.hatena.ne.jp/fumokmm/20110213/1297616436

@uehaj さんDevLOVEぐるぐるGroovyで「気楽に使おう

Groovy」http://d.hatena.ne.jp/uehaj/20110126/1296003293

とここら辺の情報を見てください

Page 21: Layout analyzerでのgroovyの利用について

Groovyってちょっと試してみたいけど、インストール面倒くさそうだよね~

自分はGroovyConsoleのWebStart版使ってます>http://d.hatena.ne.jp/bluepapa32/20101006/1286337869

ここをクリック

Page 22: Layout analyzerでのgroovyの利用について

インストールは手軽~

1. ウインドウ閉じた時に記述保持機能あるよ

2. Grape やAntBuilder(AntのDSL)も問題なしに使えます

(Grape機能を使うには、groovy-allの他にivy.jarが必要ですが、これには標準で入っています)

Page 23: Layout analyzerでのgroovyの利用について

えーっ。でも普通、他ライブラリ使ってるんだけど?

mavenにアクセス@GrabResolver でmavenURL指定標準のMavenCentralならいらない

@Grabで落としてくるライブラリ、バージョンを指定 Mavenにないライブラリは?%USERPROFILE%/.groovy/lib にライブラリを入れれば自動的に通せます

GroovyConsoleのメニューから通す事も可能 java –cp “./;lib/*” groovy.ui.GroovyMain

XXX.groovyの形でBAT起動

Page 24: Layout analyzerでのgroovyの利用について

set JAVA_HOME=C:/opt/jdk::set JAVA_OPTS=-Dgroovy.source.encoding=UTF-8 -Dfile.encoding=UTF-8

%JAVA_HOME%/bin/java %JAVA_OPTS% -cp ".;./lib/*;./libprocess/*"groovy.ui.GroovyMain processing_test.groovy

::use groovyConsole::%JAVA_HOME%/bin/java %JAVA_OPTS% -cp ".;./lib/*;./libprocess/*"groovy.ui.Console processing_test.groovy

pause

BATイメージ <デモ有

Page 25: Layout analyzerでのgroovyの利用について

具体例(https://gist.github.com/896140 )

<デモは時間があれば

import it.sauronsoftware.cron4j.*

pattern="* * * * *" //equals "*/1 * * * *" is every 1 minutes

Scheduler s = new Scheduler()

s.schedule(pattern, new Runnable() {

public void run() {

println "Another minute ticked away...${new Date()}"

}})

s.start()

try {

Thread.sleep(1000L * 60L * 2L) //60秒2回待ち

} catch (InterruptedException e) {}

s.stop()

@GrabResolver (name='gridgainsystems',root='http://www.gridgainsystems.com/maven2')

@Grab(group = 'net.sf.cron4j', module='cron4j', version='*')

Page 26: Layout analyzerでのgroovyの利用について

そんなに便利なら何でAndroidに使われてないのw

一応こんなのあります<要Linux環境

@uehaj さん解説 Groovy on android by discobot http://d.hatena.ne.jp/uehaj/20100515/1273934021

CentOS5.5で試して動かなかったのでパッチココに置きました https://github.com/kimukou/gradlestudy/tree/master/discobot

Page 27: Layout analyzerでのgroovyの利用について

package org.jggug.sampleimport android.app.Activity;import android.os.Bundleimport android.widget.TextView

public class Main extends Activity{/** Called when the activity is first created. */@Overridepublic void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState)TextView tv = new TextView(this)def list = ["Welcome","to", "discobot." , "¥nAnd", "good",

"luck", "with", "Main!",日本語もOK!"]def str = ""list.each {

str += it + " "}tv.setText(str)this.setContentView(tv)

}}

使用コードイメージ(UTF8保存)

Page 28: Layout analyzerでのgroovyの利用について

でもWinでJavaだけで

書きたい人には厳しいw Discobot環境cygwinなら動くのかな?<Win

Groovyをシェル扱いに出来ないからmkProject.sh動かない

dx.batのdex変換処理でgroovy-all.jarのクロージャクラス変換がStackOverFlowが発生してOutOfMemory出るみたい

でもWinでJavaだけで書きたい人は垣根高いよね ASEに期待したいよw(現在未サポート

Page 29: Layout analyzerでのgroovyの利用について

だからGradle等で補助(コンパイル)ツールとして使うのが吉?

Gradleってなに? Groovyで書かれたビルドツールです XMLでごちゃごちゃ書いていた記述をDSL記述で

<=pom.xml や build.xml のXML地獄からの脱出Maven、AntBuilder(AntのDSL)が使えます

時間があれば ATECのTestterを使ったデモ

使った設定はここにあります Testter

https://sites.google.com/site/androidtestclub/testter Gradle設定ファイル(use Android Gradle Plugin)

https://github.com/kimukou/gradlestudy/tree/master/testter

Page 30: Layout analyzerでのgroovyの利用について

Gradleファイル記述例buildscript {

repositories {

mavenRepo(urls: 'http://jvoegele.com/maven2/')

}

dependencies {

classpath 'com.jvoegele.gradle.plugins:android-plugin:0.9.9'

}

}

apply plugin: 'android'

repositories {

flatDir(dirs: file("$rootDir/libs"))

//mavenCentral()

}

dependencies {

compile group: 'org.twitter4j', name: 'twitter4j-core', version: '2.1.8-SNAPSHOT'

}

使うpluginをmaven

から取得する設定

使うjarとバージョンを記載

Page 31: Layout analyzerでのgroovyの利用について

Gradleファイル記述例(続き1)// プロジェクトのバージョンを設定

version = "x.y.z"

//ソース位置

[compileJava, compileTestJava]*.options.collect {options -> options.encoding= 'UTF-8'}

sourceSets.main.java.srcDirs += ['src']

ant.echo sourceSets.main.java.srcDirs

// 署名設定

androidPackage {

//keyStore = System.getProperty('user.home')+"/.android/debug.keystore"

keyStore = "${projectDir}/debug.keystore"

keyAlias = 'androiddebugkey'

// パスワードが設定されてなければ、コマンド・プロンプトで入力を求められる

keyStorePassword = "android"

keyAliasPassword = "android"

}

Page 32: Layout analyzerでのgroovyの利用について

Gradleファイル記述例(続き2)// プロジェクトのプロパティをリソースのフィルタリング(プロパティ

の解決)に使うヨ

processResources {

expand (project.properties)

}

jar {

from configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }

}

// デバッグ・ビルド設定

task configureDebug << {

jar.classifier = "debug"

}

// リリース・ビルド設定

task configureRelease << {

proguard.enabled = true

}

Apkに同梱するjarを指定します

(この記述の場合は関連全部)

Page 33: Layout analyzerでのgroovyの利用について

御静聴ありがとうございました 解析に使ったソフト

ソース位置が解りませんでした><。従ってjarを直参照

JD

谷本さん解説ページ http://goo.gl/DRWiR

本家サイト http://goo.gl/ux1I

ANDROID_HOME/Tools/libディレクトリ上で検索すると関連jarが見れます