AGPBI 関連の多量のエラーを排除する

意味不明な Gradle の Warning や Error を消して激ビルド時間短縮

解決法がなく, 待っていたがビルド時間が長すぎて非効率すぎる.

Issue リストに新しい書き込み.

A temporary workaround I managed was to rollback to 2.1.3 of gradle in my project level build.gradle. No more errors and app builds fine. Going to keep it like this until a fix is pushed out. You will be prompted to upgrade to v2.2.0 when you open AS for the project, but you can ignore it.

classpath 'com.android.tools.build:gradle:2.1.3'

Issue 215748 - android - AGPBI reports errors instead of warnings - Android Open Source Project - Issue Tracker - Google Project Hosting

なので 2.2.0 から 2.1.3 に下げる.


  dependencies {
      //classpath 'com.android.tools.build:gradle:2.2.0'
      classpath 'com.android.tools.build:gradle:2.1.3'

com.android.tools.build.gradle

再度, clean build のあと, re-start や rebuild しても以下でできず.


Error:Cause: org.gradle.api.internal.tasks.DefaultTaskInputs$TaskInputUnionFileCollection cannot be cast to org.gradle.api.internal.file.collections.DefaultConfigurableFileCollection
Possible causes for this unexpected error include:<ul><li>Gradle's dependency cache may be corrupt (this sometimes occurs after a network connection timeout.)
<a href="syncProject">Re-download dependencies and sync project (requires network)</a></li><li>The state of a Gradle build process (daemon) may be corrupt. Stopping all Gradle daemons may solve this problem.
<a href="stopGradleDaemons">Stop Gradle build processes (requires restart)</a></li><li>Your project may be using a third-party plugin which is not compatible with the other plugins in the project or the version of Gradle requested by the project.</li></ul>In the case of corrupt Gradle processes, you can also try closing the IDE and then killing all Java processes.

gradle-wrapper.properties で gradle のバージョンを下げる.


#distributionUrl=https\://services.gradle.org/distributions/gradle-3.1-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip

これでいけます. ビルド時間は, 5分の1程度に短縮された感じ.

意味がなかった proguard 記述は 無効化しておく.

proguard-rules_pro

まとめ

AGPBI 関連のエラーを消すには com.android.tools.build:gradle を 2.1.3 にダウングレードする(build.gradle root の書き換え).

com.android.tools.build:gradle:2.1.3 に対応している最新バージョンの gradle は 2.14.1(gradle-wrapper.properties の書き換え).

Gradle Distributions

2016-10-14 追記

修正された模様.

Yesterday (28 hours ago) #8 [email protected]
it seems to be fixed in Android Studio 2.2.1 with the gradle wrapper 2.2.1

Yesterday (25 hours ago) #9 [email protected]
A.S. 2.2.1 fixed it for mee too

Issue 222989 - android - Android Studio 2.2 : Build successful with 1944 errors - Android Open Source Project - Issue Tracker - Google Project Hosting

実際, 試してみたが確かに修正されていた.


  dependencies {
      classpath 'com.android.tools.build:gradle:2.2.1'

gradle 3.1 でも問題はない感じ.


意味不明な Gradle の Warning や Error を消して激ビルド時間短縮

なんとなく Gradle コンソールを開けてみると死ぬほど書き出されてるエラーやワーニング.


AGPBI: {"kind":"error","text":"(org.apache.commons.beanutils.BeanMap$8) that doesn\u0027t come with an","sources":[{}]}
AGPBI: {"kind":"error","text":"associated EnclosingMethod attribute. This class was probably produced by a","sources":[{}]}
AGPBI: {"kind":"error","text":"compiler that did not target the modern .class file format. The recommended","sources":[{}]}
AGPBI: {"kind":"error","text":"solution is to recompile the class from source, using an up-to-date compiler","sources":[{}]}
AGPBI: {"kind":"error","text":"and without specifying any \"-target\" type options. The consequence of ignoring","sources":[{}]}
AGPBI: {"kind":"error","text":"this warning is that reflective operations on this class will incorrectly","sources":[{}]}
AGPBI: {"kind":"error","text":"indicate that it is *not* an inner class.","sources":[{}]}
AGPBI: {"kind":"error","text":"warning: Ignoring InnerClasses attribute for an anonymous inner class","sources":[{}]}
AGPBI: {"kind":"error","text":"(org.apache.commons.beanutils.BeanMap$9) that doesn\u0027t come with an","sources":[{}]}
AGPBI: {"kind":"error","text":"associated EnclosingMethod attribute. This class was probably produced by a","sources":[{}]}
AGPBI: {"kind":"error","text":"compiler that did not target the modern .class file format. The recommended","sources":[{}]}
AGPBI: {"kind":"error","text":"solution is to recompile the class from source, using an up-to-date compiler","sources":[{}]}
AGPBI: {"kind":"error","text":"and without specifying any \"-target\" type options. The consequence of ignoring","sources":[{}]}
AGPBI: {"kind":"error","text":"this warning is that reflective operations on this class will incorrectly","sources":[{}]}
AGPBI: {"kind":"error","text":"indicate that it is *not* an inner class.","sources":[{}]}
AGPBI: {"kind":"error","text":"warning: Ignoring InnerClasses attribute for an anonymous inner class","sources":[{}]}
AGPBI: {"kind":"error","text":"(org.apache.commons.beanutils.BeanMap$1) that doesn\u0027t come with an","sources":[{}]}
AGPBI: {"kind":"error","text":"associated EnclosingMethod attribute. This class was probably produced by a","sources":[{}]}
AGPBI: {"kind":"error","text":"compiler that did not target the modern .class file format. The recommended","sources":[{}]}
AGPBI: {"kind":"error","text":"solution is to recompile the class from s

いつから出ていたのかわかりません.

Proguard 周りなのでしょうが, 調べても意味がわかりませんでした.

が,

Large number of errors during Gradle build after upgrading to Android Studio 2.0 - Stack Overflow

意味のない warning や error は, .idea フォルダを消すことで取り除くことができます。このフォルダは Android Studio 1.5 が作成したもので 2.0 にインポートされています。消しても自動的に作成されます。

ideadir

一度削除すると再作成されますが, 意味不明なログが吐かれなくなり, ビルド時間も数分から数十秒に激速となりました。

...

などと喜んでいたが, また出てる.

...

Issue Tacker を見てみる.

Issue 215748 - android - AGPBI reports errors instead of warnings - Android Open Source Project - Issue Tracker - Google Project Hosting

まだ生きてる issue なのですが, 一時しのぎとして以下とか.


# https://code.google.com/p/android/issues/detail?id=215748
-keepattributes Exceptions, Signature, InnerClasses, EnclosingMethod
-dontoptimize

一応出なくなりますけれども,

速くなりますけれども,

「don't optimize」て...

またはこんな一時しのぎ法も.

Issue 222989 - android - Android Studio 2.2 : Build successful with 1944 errors - Android Open Source Project - Issue Tracker - Google Project Hosting

It affects me too it is caused by gradle not android studio (but it tries to update the gradle)
Temporary solution:
I went back to gradle 2.1.3 (that I used earlier):

classpath 'com.android.tools.build:gradle:2.1.3' ->this works

If I am using classpath 'com.android.tools.build:gradle:2.2.0' I am also getting tons of warning message and the output is an unaligned file...

「com.android.tools.build:gradle のバージョンを下げる」という方法ですが, うまくダウングレードできないような...

なんなんすかね, まったく.

issues_-_android_-_android_open_source_project_-_issue_tracker_-_google_project_hosting

Issues - android - Android Open Source Project - Issue Tracker - Google Project Hosting

2016-10-05

待てないので以下でとりあえず対応.
AGPBI 関連の多量のエラーを排除する


「これより速いのがあったら言ってこい」Google非公式DIフレームワーク Tiger 登場!!

Google製のライブラリが集まっていいるGitHubリポジトリがありますが.

Google

Google

DIフレームワークが新しく登場しています.

google_tiger

google/tiger

DISCLAIMER: This is not an official Google product. Google's production dependency injection frameworks are Dagger and Guice.

Dagger や Guice があるので, このフレームワークは「非公式」ということですが, 速さの面で気持ちいい啖呵を切っているようにも見えます.

Challenge

If one found a DI framework faster, let me know. I will drop the title as long as it is proved.

「これより速いの見つけたら教えてね♥」

Group

[email protected]

と, メールアドレスもこだわっています.

サンプルを見た感じアノテーションを利用した Dagger とよく似た雰囲気になっておりますが, それぞれのスコープに対してひとつのインジェクターを生成するしくみのようです.


public class PseudoActivity {
  @Inject
  Foo foo;

  @Inject
  @BarAnnotation
  Bar bar;

  @Inject
  @BarAnnotation
  Bar bar2;

  @Inject
  Baz baz;
  
  @Inject
  Shboom shboom;

  void onCreate(DaggerApplicationComponent applicationComponent) {
    DaggerActivityComponent activityComponent =
        new DaggerActivityComponent.Builder().daggerApplicationComponent(applicationComponent).build();
    activityComponent.injectPseudoActivity(this);
  }

  @Override
  public String toString() {
    return "PseudoActivity[foo: " + foo + ", bar: " + bar + " bar2: " + bar2 + ", baz: " + baz
        + " shboom: " + shboom + "]";
  }
}

こんなかんじで最近はGoogleから実験的なライブラリが公開されるようになってきていますが, どれも微妙な雰囲気はあります.

Include the "not an official Google product" disclaimer by gk5885 · Pull Request #3 · google/tiger

これ, 今後どうなっていくのでしょうかー.

Google発リアクティブなライブラリ「Agera」の評判を眺める


75%速度向上という Gradle 3.0 を Android Studio で試す

更新されてます, Gradle が 3.0 に.

Gradle_3_0_released_-_News_-_Gradle_Forums

Gradle 3.0 released - News - Gradle Forums

Gradle_Distributions

Gradle Distributions

The Gradle Daemon is a key performance enhancer, making builds up to 75% faster, but it needed to be explicitly enabled in previous versions of Gradle. This is no longer necessary as the Daemon is now enabled by default in 3.0.

Daemon がデフォルトで起動され, 75% の速度向上らしいので.

 

Android Studio で使ってみよう

プロジェクトルートの位置で.

./gradlew wrapper --gradle-version=3.0

これで, Gradle 側はラッパーインストールできますが, Android Plugin が 2.1.x系では対応できていないようです.

最新のbetaを入れてみましょう.

com_android_tools_build_gradle

com.android.tools.build.gradle

(project-root)/build.gradle


buildscript {
  //System.properties['com.android.build.gradle.overrideVersionCheck'] = 'true'
  repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:2.2.0-beta1'
    }
}

Total time: 6.543 secs

Total time: 1.472 secs

小さいプロジェクトでも, 2回目以降のビルドで, 高速になったことが体感できます.

まあ, beta ということで少し待っていたほうがいいのかも知れませんが.

Latest Bugs topics - Gradle Forums

Android お手軽なビルド時間の短縮メモ


リアクティブにデータ更新検知して自動画面更新させる

Square 生まれのライブラリを使います.

SQLBrite

square/sqlbrite: A lightweight wrapper around SQLiteOpenHelper which introduces reactive stream semantics to SQL operations.

SQLiteOpenHelper をラップするように使い, ContentProvider(ContentResolver) のように更新を通知する役割を担当します.

SQLBrite__A_Reactive_Database_Foundation

SQLBrite: A Reactive Database Foundation

RxJava と連携させて使いましょう.


SqlBrite sqlBrite = SqlBrite.create();
BriteDatabase db = sqlBrite.wrapDatabaseHelper(openHelper, Schedulers.io());

// 対象テーブル名を含むSQLクエリーを登録
Observable<Query> users = db.createQuery("users", "SELECT * FROM users");
final AtomicInteger queries = new AtomicInteger();

// データ更新を監視して受け取る
users.subscribe(new Action1<Query>() {
  @Override public void call(Query query) {
    queries.getAndIncrement();
  }
});


System.out.println("Queries: " + queries.get()); // Prints 1

db.insert("users", createUser("jw", "Jake Wharton"));
db.insert("users", createUser("mattp", "Matt Precious"));
db.insert("users", createUser("strong", "Alec Strong"));

System.out.println("Queries: " + queries.get()); // Prints 4

このしくみを利用すると,

CursorLoader + ContentProvider

の部分を

RxJava + SQLBrite

で置き換えてリアクティブに記述できます.

MVP実装の例

googlesamples/android-architecture at dev-todo-mvp-rxjava

Observable を DataSource で作成して,

TasksLocalDataSource.java:77


    @Override
    public Observable<List<Task>> getTasks() {
        String[] projection = {
                TaskEntry.COLUMN_NAME_ENTRY_ID,
                TaskEntry.COLUMN_NAME_TITLE,
                TaskEntry.COLUMN_NAME_DESCRIPTION,
                TaskEntry.COLUMN_NAME_COMPLETED
        };
        String sql = String.format("SELECT %s FROM %s", TextUtils.join(",", projection), TaskEntry.TABLE_NAME);
        return mDatabaseHelper.createQuery(TaskEntry.TABLE_NAME, sql)
                .mapToList(mTaskMapperFunction);
    }

Repository 経由させて,

TaskRepository:96


    @Override
    public Observable<List<Task>> getTasks() {
        // ...
        if (mCacheIsDirty) {
            return remoteTasks;
        } else {

            // Query the local storage if available. If not, query the network.
            Observable<List<Task>> localTasks = mTasksLocalDataSource.getTasks();
            return Observable.concat(localTasks, remoteTasks).first();

        }
    }

Presenter 上で subscribe しておけば,

TaskPresenter:104


        Subscription subscription = mTasksRepository
                .getTasks()
                .flatMap(new Func1<List<Task>, Observable<Task>>() {
                    @Override
                    public Observable<Task> call(List<Task> tasks) {
                        return Observable.from(tasks);
                    }
                })
                .filter(new Func1<Task, Boolean>() {
		  // ...
                })
                .toList()
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer<List<Task>>() {
                    @Override
                    public void onCompleted() {
                        mTasksView.setLoadingIndicator(false);
                    }

                    @Override
                    public void onError(Throwable e) {
                        mTasksView.showLoadingTasksError();
                    }

                    @Override
                    public void onNext(List<Task> tasks) {
                        processTasks(tasks);
                    }
                });

データベースで対象テーブルに更新されるとすぐに自動的に再読み込みが実行されて画面が更新されます.

MVP に CursorLoader を利用すると, Presenter で受け取るコールバックが煩雑になりやすいのでこれを使うと便利です.

DiffUtil で簡単に RecyclerView を更新する