syncslides: Switch to retrolambda to cut down on boilerplate.

Change-Id: I760d5d2378f488790fcd3cca81b5d8e71f66af05
diff --git a/android/app/build.gradle b/android/app/build.gradle
index 54d3658..920690c 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -9,17 +9,24 @@
         // We are going to define a custom VDL service. The Vanadium
         // Gradle plugin makes that easier, so let's use that.
         classpath 'io.v:gradle-plugin:0.1'
+        // Retrolambda saves a ton on boilerplate.
+        classpath 'me.tatarka:gradle-retrolambda:3.2.4'
     }
 }
 
 apply plugin: 'android-sdk-manager'
 apply plugin: 'com.android.application'
+apply plugin: 'me.tatarka.retrolambda'
 apply plugin: 'io.v.vdl'
 
 android {
     compileSdkVersion 23
     buildToolsVersion "23.0.1"
 
+    compileOptions {
+        sourceCompatibility JavaVersion.VERSION_1_8
+        targetCompatibility JavaVersion.VERSION_1_8
+    }
     defaultConfig {
         applicationId "io.v.syncslides"
         minSdkVersion 22
diff --git a/android/app/src/main/java/io/v/syncslides/DeckChooserFragment.java b/android/app/src/main/java/io/v/syncslides/DeckChooserFragment.java
index 807b305..e3284f9 100644
--- a/android/app/src/main/java/io/v/syncslides/DeckChooserFragment.java
+++ b/android/app/src/main/java/io/v/syncslides/DeckChooserFragment.java
@@ -75,12 +75,7 @@
                              Bundle savedInstanceState) {
         View rootView = inflater.inflate(R.layout.fragment_deck_chooser, container, false);
         FloatingActionButton fab = (FloatingActionButton) rootView.findViewById(R.id.new_deck_fab);
-        fab.setOnClickListener(new View.OnClickListener() {
-            @Override
-            public void onClick(View v) {
-                onImportDeck();
-            }
-        });
+        fab.setOnClickListener(v -> onImportDeck());
         mRecyclerView = (RecyclerView) rootView.findViewById(R.id.deck_grid);
         // The cards for the decks are always the same size.
         mRecyclerView.setHasFixedSize(true);
@@ -175,11 +170,7 @@
      * background thread.
      */
     private void toast(final String msg) {
-        new Handler(Looper.getMainLooper()).post(new Runnable() {
-            @Override
-            public void run() {
-                Toast.makeText(getActivity(), msg, Toast.LENGTH_LONG).show();
-            }
-        });
+        Handler handler = new Handler(Looper.getMainLooper());
+        handler.post(() -> Toast.makeText(getActivity(), msg, Toast.LENGTH_LONG).show());
     }
 }
diff --git a/android/app/src/main/java/io/v/syncslides/DeckListAdapter.java b/android/app/src/main/java/io/v/syncslides/DeckListAdapter.java
index 0db269d..81e59e1 100644
--- a/android/app/src/main/java/io/v/syncslides/DeckListAdapter.java
+++ b/android/app/src/main/java/io/v/syncslides/DeckListAdapter.java
@@ -76,34 +76,28 @@
 
         holder.mToolbarLastOpened.setVisibility(View.VISIBLE);
         holder.mToolbarLiveNow.setVisibility(View.GONE);
-        holder.mToolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
-            @Override
-            public boolean onMenuItemClick(MenuItem item) {
-                switch (item.getItemId()) {
-                    case R.id.action_delete_deck:
-                        // TODO(kash): Implement delete.
-                        // mDB.deleteDeck(deck.getId());
-                        return true;
-                }
-                return false;
+        holder.mToolbar.setOnMenuItemClickListener(item -> {
+            switch (item.getItemId()) {
+                case R.id.action_delete_deck:
+                    // TODO(kash): Implement delete.
+                    // mDB.deleteDeck(deck.getId());
+                    return true;
             }
+            return false;
         });
 
         holder.mToolbarTitle.setText(deck.getTitle());
         holder.mThumb.setImageBitmap(deck.getThumb());
-        holder.mThumb.setOnClickListener(new View.OnClickListener() {
-            @Override
-            public void onClick(View v) {
-                Log.d(TAG, "Clicking through to PresentationActivity.");
-                String sessionId;
-                try {
-                    sessionId = mDB.createSession(deck.getId());
-                } catch (VException e) {
-                    handleError(v.getContext(), "Could not view deck.", e);
-                    return;
-                }
-                startPresentationActivity(v.getContext(), sessionId);
+        holder.mThumb.setOnClickListener(v -> {
+            Log.d(TAG, "Clicking through to PresentationActivity.");
+            String sessionId;
+            try {
+                sessionId = mDB.createSession(deck.getId());
+            } catch (VException e) {
+                handleError(v.getContext(), "Could not view deck.", e);
+                return;
             }
+            startPresentationActivity(v.getContext(), sessionId);
         });
     }
 
diff --git a/android/app/src/main/java/io/v/syncslides/NavigateFragment.java b/android/app/src/main/java/io/v/syncslides/NavigateFragment.java
index 105df9f..e475c0b 100644
--- a/android/app/src/main/java/io/v/syncslides/NavigateFragment.java
+++ b/android/app/src/main/java/io/v/syncslides/NavigateFragment.java
@@ -147,20 +147,17 @@
 //
         mSlideNumText = (TextView) rootView.findViewById(R.id.slide_num_text);
         mNotes = (EditText) rootView.findViewById(R.id.notes);
-        mNotes.setOnFocusChangeListener(new View.OnFocusChangeListener() {
-            @Override
-            public void onFocusChange(View v, boolean hasFocus) {
-                if (hasFocus) {
-                    ((PresentationActivity) getActivity()).getSupportActionBar().show();
-                    mEditing = true;
-                    getActivity().invalidateOptionsMenu();
-                    // We don't want the presentation to advance while the user
-                    // is editing the notes.  Force the app to stay on this slide.
-                    try {
-                        mSession.setLocalSlideNum(mSlideNum);
-                    } catch (VException e) {
-                        handleFatalError("Could not set local slide num", e);
-                    }
+        mNotes.setOnFocusChangeListener((v, hasFocus) -> {
+            if (hasFocus) {
+                ((PresentationActivity) getActivity()).getSupportActionBar().show();
+                mEditing = true;
+                getActivity().invalidateOptionsMenu();
+                // We don't want the presentation to advance while the user
+                // is editing the notes.  Force the app to stay on this slide.
+                try {
+                    mSession.setLocalSlideNum(mSlideNum);
+                } catch (VException e) {
+                    handleFatalError("Could not set local slide num", e);
                 }
             }
         });
diff --git a/android/app/src/main/java/io/v/syncslides/NavigationDrawerFragment.java b/android/app/src/main/java/io/v/syncslides/NavigationDrawerFragment.java
index 5276e17..509824b 100644
--- a/android/app/src/main/java/io/v/syncslides/NavigationDrawerFragment.java
+++ b/android/app/src/main/java/io/v/syncslides/NavigationDrawerFragment.java
@@ -100,12 +100,8 @@
                              Bundle savedInstanceState) {
         mDrawerListView = (ListView) inflater.inflate(
                 R.layout.fragment_navigation_drawer, container, false);
-        mDrawerListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
-            @Override
-            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
-                selectItem(position);
-            }
-        });
+        mDrawerListView.setOnItemClickListener(
+                (parent, view, position, id) -> selectItem(position));
         mDrawerListView.setAdapter(new ArrayAdapter<String>(
                 getActionBar().getThemedContext(),
                 android.R.layout.simple_list_item_activated_2,
@@ -190,12 +186,7 @@
         }
 
         // Defer code dependent on restoration of previous instance state.
-        mDrawerLayout.post(new Runnable() {
-            @Override
-            public void run() {
-                mDrawerToggle.syncState();
-            }
-        });
+        mDrawerLayout.post(() -> mDrawerToggle.syncState());
 
         mDrawerLayout.setDrawerListener(mDrawerToggle);
     }
diff --git a/android/app/src/main/java/io/v/syncslides/SignInActivity.java b/android/app/src/main/java/io/v/syncslides/SignInActivity.java
index 2e571c2..8fc2adb 100644
--- a/android/app/src/main/java/io/v/syncslides/SignInActivity.java
+++ b/android/app/src/main/java/io/v/syncslides/SignInActivity.java
@@ -197,13 +197,10 @@
                 new Bundle(),
                 false,
                 new OnTokenAcquired(),
-                new Handler(new Handler.Callback() {
-                    @Override
-                    public boolean handleMessage(Message msg) {
-                        Log.e(TAG, "Error getting auth token: " + msg.toString());
-                        fetchUserProfileDone(null);
-                        return true;
-                    }
+                new Handler(msg -> {
+                    Log.e(TAG, "Error getting auth token: " + msg.toString());
+                    fetchUserProfileDone(null);
+                    return true;
                 }));
     }
 
diff --git a/android/app/src/main/java/io/v/syncslides/SlideListAdapter.java b/android/app/src/main/java/io/v/syncslides/SlideListAdapter.java
index 2019fa6..add52c7 100644
--- a/android/app/src/main/java/io/v/syncslides/SlideListAdapter.java
+++ b/android/app/src/main/java/io/v/syncslides/SlideListAdapter.java
@@ -36,12 +36,9 @@
     public SlideListAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
         View v = LayoutInflater.from(parent.getContext())
                 .inflate(R.layout.slide_card, parent, false);
-        v.setOnClickListener(new View.OnClickListener() {
-            @Override
-            public void onClick(View v) {
-                int position = mRecyclerView.getChildAdapterPosition(v);
-                ((PresentationActivity) v.getContext()).navigateToSlide(position);
-            }
+        v.setOnClickListener(v1 -> {
+            int position = mRecyclerView.getChildAdapterPosition(v1);
+            ((PresentationActivity) v1.getContext()).navigateToSlide(position);
         });
         return new ViewHolder(v);
     }
diff --git a/android/app/src/main/java/io/v/syncslides/SlideListFragment.java b/android/app/src/main/java/io/v/syncslides/SlideListFragment.java
index 577ec8b..9c382c3 100644
--- a/android/app/src/main/java/io/v/syncslides/SlideListFragment.java
+++ b/android/app/src/main/java/io/v/syncslides/SlideListFragment.java
@@ -70,15 +70,12 @@
             final FloatingActionButton fab = (FloatingActionButton) rootView.findViewById(
                     R.id.play_presentation_fab);
             fab.setVisibility(View.VISIBLE);
-            fab.setOnClickListener(new View.OnClickListener() {
-                @Override
-                public void onClick(View v) {
-                    // TODO(kash): Implement me.
+            fab.setOnClickListener(v -> {
+                // TODO(kash): Implement me.
 //                    mRole = Role.PRESENTER;
 //                    fab.setVisibility(View.INVISIBLE);
 //                    PresentationActivity activity = (PresentationActivity) v.getContext();
 //                    activity.startPresentation();
-                }
             });
         }
         mRecyclerView = (RecyclerView) rootView.findViewById(R.id.slide_list);
diff --git a/android/app/src/main/java/io/v/syncslides/db/SlideNumberWatcher.java b/android/app/src/main/java/io/v/syncslides/db/SlideNumberWatcher.java
index 4440179..15d3e10 100644
--- a/android/app/src/main/java/io/v/syncslides/db/SlideNumberWatcher.java
+++ b/android/app/src/main/java/io/v/syncslides/db/SlideNumberWatcher.java
@@ -73,18 +73,8 @@
         if (mListeners.size() == 1) {
             // First listener.  Start the threads.
             mCurrentContext = mBaseContext.withCancel();
-            mExecutor.submit(new Runnable() {
-                @Override
-                public void run() {
-                    watchLocalSlideNum();
-                }
-            });
-            mExecutor.submit(new Runnable() {
-                @Override
-                public void run() {
-                    watchCurrentSlide();
-                }
-            });
+            mExecutor.submit(() -> watchLocalSlideNum());
+            mExecutor.submit(() -> watchCurrentSlide());
         }
         listener.onChange(getSlideNum());
     }
@@ -140,12 +130,7 @@
             if (sync(presentations.getRow(rowKey).exists(mCurrentContext))) {
                 final VCurrentSlide slide = (VCurrentSlide) presentations.get(
                         mCurrentContext, rowKey, VCurrentSlide.class);
-                mHandler.post(new Runnable() {
-                    @Override
-                    public void run() {
-                        currentSlideChanged(slide);
-                    }
-                });
+                mHandler.post(() -> currentSlideChanged(slide));
             }
             ResumeMarker marker = sync(batch.getResumeMarker(mCurrentContext));
             VIterable<WatchChange> changes =
@@ -160,21 +145,11 @@
                 if (change.getChangeType().equals(ChangeType.PUT_CHANGE)) {
                     final VCurrentSlide slide = (VCurrentSlide) VomUtil.decode(
                             change.getVomValue(), VCurrentSlide.class);
-                    mHandler.post(new Runnable() {
-                        @Override
-                        public void run() {
-                            currentSlideChanged(slide);
-                        }
-                    });
+                    mHandler.post(() -> currentSlideChanged(slide));
                 }
             }
         } catch (final VException e) {
-            mHandler.post(new Runnable() {
-                @Override
-                public void run() {
-                    notifyError(e);
-                }
-            });
+            mHandler.post(() -> notifyError(e));
         }
     }
 
@@ -185,12 +160,7 @@
             Table ui = batch.getTable(SyncbaseDB.UI_TABLE);
             final VSession vSession = (VSession) sync(ui.get(
                     mCurrentContext, mSessionId, VSession.class));
-            mHandler.post(new Runnable() {
-                @Override
-                public void run() {
-                    localSlideChanged(vSession.getLocalSlide());
-                }
-            });
+            mHandler.post(() -> localSlideChanged(vSession.getLocalSlide()));
             ResumeMarker marker = sync(batch.getResumeMarker(mCurrentContext));
             VIterable<WatchChange> changes =
                     sync(mDb.watch(mCurrentContext, SyncbaseDB.UI_TABLE, mSessionId, marker));
@@ -203,21 +173,11 @@
                 if (change.getChangeType().equals(ChangeType.PUT_CHANGE)) {
                     final VSession vSession1 = (VSession) VomUtil.decode(
                             change.getVomValue(), VSession.class);
-                    mHandler.post(new Runnable() {
-                        @Override
-                        public void run() {
-                            localSlideChanged(vSession1.getLocalSlide());
-                        }
-                    });
+                    mHandler.post(() -> localSlideChanged(vSession1.getLocalSlide()));
                 }
             }
         } catch (final VException e) {
-            mHandler.post(new Runnable() {
-                @Override
-                public void run() {
-                    notifyError(e);
-                }
-            });
+            mHandler.post(() -> notifyError(e));
         }
     }
 }
diff --git a/android/app/src/main/java/io/v/syncslides/db/SlideWatcher.java b/android/app/src/main/java/io/v/syncslides/db/SlideWatcher.java
index a69b9cf..30d0aa2 100644
--- a/android/app/src/main/java/io/v/syncslides/db/SlideWatcher.java
+++ b/android/app/src/main/java/io/v/syncslides/db/SlideWatcher.java
@@ -49,14 +49,11 @@
             fetchInitialState(context, listener, batch);
             // Need to watch two tables, but the API allows watching only one
             // table at a time.  Start another thread for watching the notes.
-            new Thread(new Runnable() {
-                @Override
-                public void run() {
-                    try {
-                        watchNoteChanges(context, listener, watchMarker);
-                    } catch (VException e) {
-                        listener.onError(e);
-                    }
+            new Thread(() -> {
+                try {
+                    watchNoteChanges(context, listener, watchMarker);
+                } catch (VException e) {
+                    listener.onError(e);
                 }
             }).start();
             watchSlideChanges(context, listener, watchMarker);
diff --git a/android/app/src/main/java/io/v/syncslides/db/SyncbaseDB.java b/android/app/src/main/java/io/v/syncslides/db/SyncbaseDB.java
index 1580df3..4b314e7 100644
--- a/android/app/src/main/java/io/v/syncslides/db/SyncbaseDB.java
+++ b/android/app/src/main/java/io/v/syncslides/db/SyncbaseDB.java
@@ -197,16 +197,13 @@
 
     @Override
     public ListenableFuture<Void> importDeck(final Deck deck, final Slide[] slides) {
-        return mExecutorService.submit(new Callable<Void>() {
-            @Override
-            public Void call() throws Exception {
-                putDeck(deck);
-                for (int i = 0; i < slides.length; ++i) {
-                    Slide slide = slides[i];
-                    putSlide(deck.getId(), i, slide);
-                }
-                return null;
+        return mExecutorService.submit(() -> {
+            putDeck(deck);
+            for (int i = 0; i < slides.length; ++i) {
+                Slide slide = slides[i];
+                putSlide(deck.getId(), i, slide);
             }
+            return null;
         });
     }
 
diff --git a/android/app/src/main/java/io/v/syncslides/db/WatchedList.java b/android/app/src/main/java/io/v/syncslides/db/WatchedList.java
index 4ab9cd1..10955b1 100644
--- a/android/app/src/main/java/io/v/syncslides/db/WatchedList.java
+++ b/android/app/src/main/java/io/v/syncslides/db/WatchedList.java
@@ -63,50 +63,24 @@
         if (mListeners.size() == 1) {
             // First listener.  Start the thread.
             mCurrentContext = mBaseContext.withCancel();
-            mExecutor.submit(new Runnable() {
+            mExecutor.submit(() -> mWatcher.watch(mCurrentContext, new Watcher.Listener<E>() {
                 @Override
-                public void run() {
-                    mWatcher.watch(mCurrentContext, new Watcher.Listener<E>() {
-                        // TODO(kash): Switch to retrolambda to save on the boilerplate.
-                        @Override
-                        public void onPut(final E elem) {
-                            mHandler.post(new Runnable() {
-                                @Override
-                                public void run() {
-                                    put(elem);
-                                }
-                            });
-                        }
-
-                        @Override
-                        public void onDelete(final E elem) {
-                            mHandler.post(new Runnable() {
-                                @Override
-                                public void run() {
-                                    delete(elem);
-                                }
-                            });
-                        }
-
-                        @Override
-                        public void onError(final Exception e) {
-                            mHandler.post(new Runnable() {
-                                @Override
-                                public void run() {
-                                    error(e);
-                                }
-                            });
-                        }
-                    });
+                public void onPut(final E elem) {
+                    mHandler.post(() -> put(elem));
                 }
-            });
+
+                @Override
+                public void onDelete(final E elem) {
+                    mHandler.post(() -> delete(elem));
+                }
+
+                @Override
+                public void onError(final Exception e) {
+                    mHandler.post(() -> error(e));
+                }
+            }));
         }
-        mHandler.post(new Runnable() {
-            @Override
-            public void run() {
-                listener.notifyDataSetChanged();
-            }
-        });
+        mHandler.post(() -> listener.notifyDataSetChanged());
     }
 
     @Override
diff --git a/android/app/src/main/java/io/v/syncslides/lib/DeckImporter.java b/android/app/src/main/java/io/v/syncslides/lib/DeckImporter.java
index 3b9c0fa..4756cf4 100644
--- a/android/app/src/main/java/io/v/syncslides/lib/DeckImporter.java
+++ b/android/app/src/main/java/io/v/syncslides/lib/DeckImporter.java
@@ -77,12 +77,7 @@
     }
 
     public ListenableFuture<Void> importDeck(final DocumentFile dir) {
-        return mExecutorService.submit(new Callable<Void>() {
-            @Override
-            public Void call() throws Exception {
-                return importDeckImpl(dir);
-            }
-        });
+        return mExecutorService.submit(() -> importDeckImpl(dir));
     }
 
     private Void importDeckImpl(DocumentFile dir) throws ImportException {