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

2,915 views
2,848 views

Published on

Published in: Technology
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
2,915
On SlideShare
0
From Embeds
0
Number of Embeds
40
Actions
Shares
0
Downloads
7
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

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

  1. 1. LayoutAnalyzerでのGroovyの 利用について 2011/04/09 @kimukou_26
  2. 2. 自己紹介Kimukou_26 といいます 関東でフリーのSEしています 主に参加している勉強会 JGGUG ・・ Grails/Groovy #jggug ATEC ・・Android テスト部 #android_tec あまり貢献できてません。すみません>< 今回は #yapf には勉強しにきたつもりが。。  何故か発表する事にw
  3. 3. 今回話す事になったきっかけ
  4. 4. では解析してみましょう使っているツールは? Layoutopt 日本語解説サイト http://goo.gl/QCMij 本家解説サイト http://goo.gl/7cdt7どんなツール?  レイアウト.xmlの最適度チェックツール  あくまでナビゲーションだけで変更はしないよ どこでGroovyを使っているの? useスコープ内だと対象 クラスでCategoryAの  XMLの解析Rule(GroovyRule) ルール(処理)が  Use Category(クラスに機能を後付けする機能) 使えるイメージ use(CategoryA){ 対象クラス、 CategoryA Clousre A() / B() }
  5. 5. Groovyで実際使うとこんなイメージclass ExcelCategory { /** ファイルを読み込む */ static void readXls(File self, Closure yield){ Fileクラスに readXls() //読込処理 関数が追加された } イメージ /** ファイルを編集する */ static void editXls(File self, Closure yield){ //編集処理 }} File selfuse (ExcelCategory) { の参照 new File(hogehoge.xls).readXls{ excelApp -> // hogehoge.xlsに対する何かしらの処理 } }}
  6. 6. どんな構成になっているの? 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)
  7. 7. 処理の流れの抜粋 Layoutopt.jarcom.android.layoutopt.cli.Mainvoid main(String[] args) static void analyzeFiles(File[] files) LayoutAnalyzer analyzer = new LayoutAnalyzer(); static void analyze(LayoutAnalyzer analyzer, File file) LayoutAnalysis analysis = analyzer.analyze(file); uix.jarcom.android.layoutopt.uix.LayoutAnalyzer LayoutAnalyzer() loadRules() loadRule
  8. 8. GroovyShellを 初期化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)); } public void addRule(Rule rule) が あるので外からRule追加は可能 かとcom.android.layoutopt.uix.rules.GroovyRuleimport 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;
  9. 9.  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; Closure this.mScript = script; this.mBinding = new Binding(); this.mScript.setBinding(this.mBinding); Uix.jar this.mClosure = new Closure(this) { Rules/XX.rule public Object call() { を読み込んだスクリプトファ return GroovyRule.this.mScript.run(); イルデータ } }; this.mCategories = new ArrayList(); 適応する Collections.addAll(this.mCategories, Categoryクラス new Class[]{ を配列定義 DOMCategory.class, LayoutAnalysisCategory.class }); }
  10. 10. 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();}
  11. 11. 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で行っています
  12. 12. uix.jar内のruleファイルにuse適応 している認識が正のようです rules/XX.rule <= 実は groovyファイル
  13. 13. uix.jarの Rules/ UselessLayout.rule ファイル// Rule: UselessLayout//// Description: Checks whether current node can be removed.//// Conditions: com.android.layoutopt.uix.groovy.LayoutA// - The node has children nalysisCategory// - The node does not have siblings public static LayoutAnalysis leftShift(// - The nodes 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"}"}
  14. 14. com.android.layoutopt.uix.groovy.LayoutAnalysisCategory public static int getStartLine(Node node) public static int getEndLine(Node node)com.android.layoutopt.uix.groovy.LayoutAnalysisCategory public static class Issue 内部Innerクラスで使っている からあえて宣言書いていると思われ com.android.layoutopt.uix.LayoutAnalysis public int getStartLine() { return LayoutAnalysisCategory.getStartLine(this.mNode); } public int getEndLine() { return LayoutAnalysisCategory.getEndLine(this.mNode); }
  15. 15. 他のG系の技術を使ったコード•GString ・・String型のGroovy拡張クラスです •@fumokmm さん解説サイト http://d.hatena.ne.jp/fumokmm/20110323/ 計算式OK •Groovyコード上だと • int num=2 • String aaa=“ほげほげ$num ${num/20}” と書けます • String bbb=‘まいう’ • シングルで囲むと普通のString型 com.android.layoutopt.uix.groovy.LayoutAnalysisCategoryimport groovy.lang.GString; public static LayoutAnalysis leftShift( LayoutAnalysis analysis, GString description){ analysis.addIssue(description.toString()); return analysis; }
  16. 16. •DOMCategory ・・ DOM操作を簡単にするCategory定義クラス • XML読み(英語) http://goo.gl/SPG93 • XML書き(英語) http://goo.gl/nPxqO •@nobusue さんサンプル •https://gist.github.com/619066 com.android.layoutopt.uix.groovy.LayoutAnalysisCategoryimport 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; }
  17. 17. Groovyは何が美味しいの?Javaは実行コンパイル面倒スクリプトで実行したい!Java実行スクリプトJRubyで書けるけど、Ruby文 法で書き直すの嫌だよねXXX.java=>XXX.groovyと拡張子変更だけで 実行できると楽だよね  GroovyConsoleだと拡張子Javaでも実行可能  groovyConsoleで多少の修正で動作可能  配列記述 「}」 =>「]」 に修正もっとシンプルに書こうよーJSみたい クロージャ等使って
  18. 18. 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とここら辺の情報を見てください
  19. 19. Groovyってちょっと試してみたいけど、 インストール面倒くさそうだよね~ 自分はGroovyConsoleのWebStart版使ってます >http://d.hatena.ne.jp/bluepapa32/20101006/1286337869 ここをクリック
  20. 20. インストールは手軽~1. ウインドウ閉じた時に記 述保持機能あるよ2. Grape やAntBuilder(Ant のDSL)も問題なしに使え ます(Grape機能を使うには、 groovy-allの他にivy.jar が必要ですが、これには 標準で入っています)
  21. 21. えーっ。でも普通、 他ライブラリ使ってるんだけど? mavenにアクセス @GrabResolver でmavenURL指定 標準のMavenCentralならいらない @Grabで落としてくるライブラリ、バージョンを指定 Mavenにないライブラリは? %USERPROFILE%/.groovy/lib にライブラリ を入れれば自動的に通せます GroovyConsoleのメニューから通す事も可能 java –cp “./;lib/*” groovy.ui.GroovyMain XXX.groovy の形でBAT起動
  22. 22. BATイメージ <デモ有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.groovypause
  23. 23. 具体例(https://gist.github.com/896140 ) <デモは時間があれば (name= gridgainsystems ,root= (group = net. . , module= cron4j , version= ) pattern= Scheduler s = Scheduler() s. (pattern, Runnable() { () { println }}) s. () { Thread. ( * * ) //60秒2回待ち } (InterruptedException e) {} s. ()
  24. 24. そんなに便利なら何で 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
  25. 25. 使用コードイメージ(UTF8保存)package org.jggug.sampleimport android.app.Activity;import android.os.Bundleimport android.widget.TextViewpublic class Main extends Activity{ /** Called when the activity is first created. */ @Override public 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) }}
  26. 26. でもWinでJavaだけで 書きたい人には厳しいw Discobot環境cygwinなら動くのかな?<Win  Groovyをシェル扱いに出来ないからmkProject.sh 動かない  dx.batのdex変換処理でgroovy-all.jarのクロージャクラ ス変換がStackOverFlowが発生してOutOfMemory出るみた い でもWinでJavaだけで書きたい人は垣根高いよね  ASEに期待したいよw(現在未サポート
  27. 27. だから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
  28. 28. Gradleファイル記述例buildscript { repositories { mavenRepo(urls: http://jvoegele.com/maven2/) } dependencies { classpath com.jvoegele.gradle.plugins:android-plugin:0.9.9 }}apply plugin: android 使うpluginをmavenrepositories { から取得する設定 flatDir(dirs: file("$rootDir/libs")) //mavenCentral() 使うjarと} バージョンを記載dependencies { compile group: org.twitter4j, name: twitter4j-core, version: 2.1.8- SNAPSHOT}
  29. 29. 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"}
  30. 30. Gradleファイル記述例(続き2)// プロジェクトのプロパティをリソースのフィルタリング(プロパティ の解決)に使うヨprocessResources { expand (project.properties)}jar { from configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }}// デバッグ・ビルド設定task configureDebug << { jar.classifier = "debug" Apkに同梱する} jarを指定します// リリース・ビルド設定 (この記述の場合はtask configureRelease << { 関連全部) proguard.enabled = true}
  31. 31. 御静聴ありがとうございました 解析に使ったソフト ANDROID_HOME/  ソース位置が解りませんでした><。 Tools/libディレクトリ上で検 従ってjarを直参照 索すると関連jarが見れます JD 谷本さん解説ページ http://goo.gl/DRWiR 本家サイト http://goo.gl/ux1I

×