diff options
| author | Keith Packard <keithp@keithp.com> | 2014-08-17 20:48:23 -0700 | 
|---|---|---|
| committer | Keith Packard <keithp@keithp.com> | 2014-08-17 20:48:23 -0700 | 
| commit | 59dfe661fcb504f390d9726378c676f2b5b005f3 (patch) | |
| tree | 3b04fce1f5365ba7f98768dcaa3b29bfbb0afcb4 | |
| parent | b1f1844aa514893228080704da3b3ccf855bda1e (diff) | |
altosdroid: Skip updating hidden UI elements
Instead of updating everything in the UI, only update the visible UI
elements to save a bunch of computation.
Signed-off-by: Keith Packard <keithp@keithp.com>
10 files changed, 190 insertions, 48 deletions
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java index a599698f..484efaf8 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java @@ -174,18 +174,29 @@ public class AltosBluetooth extends AltosLink {  		} catch (InterruptedException e) {  			connection_lost();  		} -	}		 +	} + +	private static final int buffer_size = 1024; + +	private byte[] buffer = new byte[buffer_size]; +	private int buffer_len = 0; +	private int buffer_off = 0;  	public int getchar() { -		try { -			wait_connected(); -			return input.read(); -		} catch (IOException e) { -			connection_lost(); -		} catch (java.lang.InterruptedException e) { -			connection_lost(); +		while (buffer_off == buffer_len) { +			try { +				wait_connected(); +				buffer_len = input.read(buffer); +				buffer_off = 0; +			} catch (IOException e) { +				connection_lost(); +				return AltosLink.ERROR; +			} catch (java.lang.InterruptedException e) { +				connection_lost(); +				return AltosLink.ERROR; +			}  		} -		return AltosLink.ERROR; +		return buffer[buffer_off++];  	}  	public void close() { diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java index 563ccd5a..c9c38d98 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java @@ -37,6 +37,7 @@ import android.os.Message;  import android.os.Messenger;  import android.os.RemoteException;  import android.support.v4.app.FragmentActivity; +import android.support.v4.app.FragmentManager;  import android.util.DisplayMetrics;  import android.util.Log;  import android.view.Menu; @@ -53,8 +54,8 @@ import org.altusmetrum.altoslib_5.*;  public class AltosDroid extends FragmentActivity {  	// Debugging -	private static final String TAG = "AltosDroid"; -	private static final boolean D = true; +	static final String TAG = "AltosDroid"; +	static final boolean D = true;  	// Message types received by our Handler  	public static final int MSG_STATE_CHANGE    = 1; @@ -67,6 +68,8 @@ public class AltosDroid extends FragmentActivity {  	private static final int REQUEST_CONNECT_DEVICE = 1;  	private static final int REQUEST_ENABLE_BT      = 2; +	public static FragmentManager	fm; +  	// Layout Views  	private TextView mTitle; @@ -145,6 +148,7 @@ public class AltosDroid extends FragmentActivity {  				ad.set_location((Location) msg.obj);  				break;  			case MSG_CRC_ERROR: +				break;  			case MSG_UPDATE_AGE:  				if (ad.saved_state != null) {  					ad.mAgeView.setText(String.format("%d", (System.currentTimeMillis() - ad.saved_state.received_time + 500) / 1000)); @@ -206,13 +210,29 @@ public class AltosDroid extends FragmentActivity {  	void set_location(Location location) {  		saved_location = location; +		Log.d(TAG, "set_location");  		update_ui(saved_state);  	} +	boolean same_string(String a, String b) { +		if (a == null) { +			if (b == null) +				return true; +			return false; +		} else { +			if (b == null) +				return false; +			return a.equals(b); +		} +	} +  	void update_ui(AltosState state) { + +		Log.d(TAG, "update_ui");  		if (state != null && saved_state != null) {  			if (saved_state.state != state.state) {  				String currentTab = mTabHost.getCurrentTabTag(); +				Log.d(TAG, "switch state");  				switch (state.state) {  				case AltosLib.ao_flight_boost:  					if (currentTab.equals("pad")) mTabHost.setCurrentTabByTag("ascent"); @@ -226,7 +246,6 @@ public class AltosDroid extends FragmentActivity {  				}  			}  		} -		saved_state = state;  		AltosGreatCircle from_receiver = null; @@ -243,18 +262,35 @@ public class AltosDroid extends FragmentActivity {  		}  		if (state != null) { -			mCallsignView.setText(state.callsign); -			mSerialView.setText(String.format("%d", state.serial)); -			mFlightView.setText(String.format("%d", state.flight)); -			mStateView.setText(state.state_name()); -			mRSSIView.setText(String.format("%d", state.rssi)); +			if (saved_state == null || !same_string(saved_state.callsign, state.callsign)) { +				Log.d(TAG, "update callsign"); +				mCallsignView.setText(state.callsign); +			} +			if (saved_state == null || state.serial != saved_state.serial) { +				Log.d(TAG, "update serial"); +				mSerialView.setText(String.format("%d", state.serial)); +			} +			if (saved_state == null || state.flight != saved_state.flight) { +				Log.d(TAG, "update flight"); +				mFlightView.setText(String.format("%d", state.flight)); +			} +			if (saved_state == null || state.state != saved_state.state) { +				Log.d(TAG, "update state"); +				mStateView.setText(state.state_name()); +			} +			if (saved_state == null || state.rssi != saved_state.rssi) { +				Log.d(TAG, "update rssi"); +				mRSSIView.setText(String.format("%d", state.rssi)); +			}  		}  		for (AltosDroidTab mTab : mTabs) -			mTab.update_ui(state, from_receiver, saved_location); +			mTab.update_ui(state, from_receiver, saved_location, mTab == mTabsAdapter.currentItem());  		if (state != null)  			mAltosVoice.tell(state); + +		saved_state = state;  	}  	private void onTimerTick() { @@ -294,6 +330,8 @@ public class AltosDroid extends FragmentActivity {  		super.onCreate(savedInstanceState);  		if(D) Log.e(TAG, "+++ ON CREATE +++"); +		fm = getSupportFragmentManager(); +  		// Get local Bluetooth adapter  		mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidTab.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidTab.java index 20593bd5..b960eb1a 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidTab.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidTab.java @@ -19,7 +19,57 @@ package org.altusmetrum.AltosDroid;  import org.altusmetrum.altoslib_5.*;  import android.location.Location; +import android.app.Activity; +import android.graphics.Color; +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentTransaction; +import android.support.v4.app.FragmentManager; +import android.location.Location; +import android.util.Log; + +public abstract class AltosDroidTab extends Fragment { +	AltosState		last_state; +	AltosGreatCircle	last_from_receiver; +	Location		last_receiver; + +	public abstract void show(AltosState state, AltosGreatCircle from_receiver, Location receiver); + +	public abstract String tab_name(); + +	public void set_visible(boolean visible) { +		FragmentTransaction	ft = AltosDroid.fm.beginTransaction(); +		if (visible) +			ft.show(this); +		else +			ft.hide(this); +		ft.commit(); +	} + +	public void update_ui(AltosState state, AltosGreatCircle from_receiver, Location receiver, boolean is_current) { +		if (is_current) { +			Log.d(AltosDroid.TAG, String.format("%s: visible, performing update", tab_name())); + +			show(state, from_receiver, receiver); +		} else { +			Log.d(AltosDroid.TAG, String.format("%s: not visible, skipping update", tab_name())); +			last_state = state; +			last_from_receiver = from_receiver; +			last_receiver = receiver; +			return; +		} +	} + +	public void onHiddenChanged(boolean hidden) { +		if (last_state != null && isVisible()) { +			AltosState		state = last_state; +			AltosGreatCircle	from_receiver = last_from_receiver; +			Location		receiver = last_receiver; -public interface AltosDroidTab { -	public void update_ui(AltosState state, AltosGreatCircle from_receiver, Location receiver); +			last_state = null; +			last_from_receiver = null; +			last_receiver = null; +			show(state, from_receiver, receiver); +		} +	}  } diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosVoice.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosVoice.java index 147405f6..b05913b6 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosVoice.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosVoice.java @@ -45,7 +45,7 @@ public class AltosVoice {  	} -	public void speak(String s) { +	public synchronized void speak(String s) {  		if (!tts_enabled) return;  		tts.speak(s, TextToSpeech.QUEUE_ADD, null);  	} @@ -87,7 +87,8 @@ public class AltosVoice {  			}  		}  		old_state = state; -		idle_thread.notice(state, spoke); +		if (idle_thread != null) +			idle_thread.notice(state, spoke);  	} @@ -117,13 +118,20 @@ public class AltosVoice {  			     state.state == AltosLib.ao_flight_stateless) &&  			    state.range >= 0)  			{ -				speak(String.format("Height %d, bearing %s %d, elevation %d, range %d.\n", -				                    (int) (state.height() + 0.5), -	                                state.from_pad.bearing_words( -	                                      AltosGreatCircle.BEARING_VOICE), -				                    (int) (state.from_pad.bearing + 0.5), -				                    (int) (state.elevation + 0.5), -				                    (int) (state.range + 0.5))); +				if (state.from_pad != null) { +					speak(String.format("Height %d, bearing %s %d, elevation %d, range %d.\n", +							    (int) (state.height() + 0.5), +							    state.from_pad.bearing_words( +								    AltosGreatCircle.BEARING_VOICE), +							    (int) (state.from_pad.bearing + 0.5), +							    (int) (state.elevation + 0.5), +							    (int) (state.range + 0.5))); +				} else { +					speak(String.format("Height %d, elevation %d, range %d.\n", +							    (int) (state.height() + 0.5), +							    (int) (state.elevation + 0.5), +							    (int) (state.range + 0.5))); +				}  			} else if (state.state > AltosLib.ao_flight_pad) {  				if (state.height() != AltosLib.MISSING)  					speak(String.format("%d meters", (int) (state.height() + 0.5))); diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TabAscent.java b/altosdroid/src/org/altusmetrum/AltosDroid/TabAscent.java index cb9fd5c8..c146c277 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/TabAscent.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/TabAscent.java @@ -29,7 +29,7 @@ import android.widget.ImageView;  import android.widget.TextView;  import android.location.Location; -public class TabAscent extends Fragment implements AltosDroidTab { +public class TabAscent extends AltosDroidTab {  	AltosDroid mAltosDroid;  	private TextView mHeightView; @@ -85,7 +85,11 @@ public class TabAscent extends Fragment implements AltosDroidTab {  		mAltosDroid = null;  	} -	public void update_ui(AltosState state, AltosGreatCircle from_receiver, Location receiver) { +	public String tab_name() { +		return "ascent"; +	} + +	public void show(AltosState state, AltosGreatCircle from_receiver, Location receiver) {  		if (state != null) {  			mHeightView.setText(AltosDroid.number("%6.0f m", state.height()));  			mMaxHeightView.setText(AltosDroid.number("%6.0f m", state.max_height())); diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TabDescent.java b/altosdroid/src/org/altusmetrum/AltosDroid/TabDescent.java index 2171afa4..6d781efd 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/TabDescent.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/TabDescent.java @@ -29,7 +29,7 @@ import android.widget.ImageView;  import android.widget.TextView;  import android.location.Location; -public class TabDescent extends Fragment implements AltosDroidTab { +public class TabDescent extends AltosDroidTab {  	AltosDroid mAltosDroid;  	private TextView mSpeedView; @@ -89,7 +89,9 @@ public class TabDescent extends Fragment implements AltosDroidTab {  		mAltosDroid = null;  	} -	public void update_ui(AltosState state, AltosGreatCircle from_receiver, Location receiver) { +	public String tab_name() { return "descent"; } + +	public void show(AltosState state, AltosGreatCircle from_receiver, Location receiver) {  		if (state != null) {  			mSpeedView.setText(AltosDroid.number("%6.0f m/s", state.speed()));  			mHeightView.setText(AltosDroid.number("%6.0f m", state.height())); diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TabLanded.java b/altosdroid/src/org/altusmetrum/AltosDroid/TabLanded.java index 47e41d59..16427d8b 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/TabLanded.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/TabLanded.java @@ -28,7 +28,7 @@ import android.view.ViewGroup;  import android.widget.TextView;  import android.location.Location; -public class TabLanded extends Fragment implements AltosDroidTab { +public class TabLanded extends AltosDroidTab {  	AltosDroid mAltosDroid;  	private TextView mBearingView; @@ -73,7 +73,9 @@ public class TabLanded extends Fragment implements AltosDroidTab {  		mAltosDroid = null;  	} -	public void update_ui(AltosState state, AltosGreatCircle from_receiver, Location receiver) { +	public String tab_name() { return "landed"; } + +	public void show(AltosState state, AltosGreatCircle from_receiver, Location receiver) {  		if (from_receiver != null) {  			mBearingView.setText(String.format("%3.0f°", from_receiver.bearing));  			mDistanceView.setText(String.format("%6.0f m", from_receiver.distance)); @@ -87,12 +89,11 @@ public class TabLanded extends Fragment implements AltosDroidTab {  			mReceiverLatitudeView.setText(AltosDroid.pos(receiver.getLatitude(), "N", "S"));  			mReceiverLongitudeView.setText(AltosDroid.pos(receiver.getLongitude(), "W", "E"));  		} -	        +  		if (state != null) {  			mMaxHeightView.setText(String.format("%6.0f m", state.max_height()));  			mMaxAccelView.setText(String.format("%6.0f m/s²", state.max_acceleration()));  			mMaxSpeedView.setText(String.format("%6.0f m/s", state.max_speed()));  		}  	} -  } diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TabMap.java b/altosdroid/src/org/altusmetrum/AltosDroid/TabMap.java index 15dc8bf7..811e5482 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/TabMap.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/TabMap.java @@ -42,7 +42,7 @@ import android.view.ViewGroup;  import android.widget.TextView;  import android.location.Location; -public class TabMap extends Fragment implements AltosDroidTab { +public class TabMap extends AltosDroidTab {  	AltosDroid mAltosDroid;  	private SupportMapFragment mMapFragment; @@ -51,6 +51,7 @@ public class TabMap extends Fragment implements AltosDroidTab {  	private Marker mRocketMarker;  	private Marker mPadMarker; +	private boolean pad_set;  	private Polyline mPolyline;  	private TextView mDistanceView; @@ -152,7 +153,9 @@ public class TabMap extends Fragment implements AltosDroidTab {  		}  	} -	public void update_ui(AltosState state, AltosGreatCircle from_receiver, Location receiver) { +	public String tab_name() { return "map"; } + +	public void show(AltosState state, AltosGreatCircle from_receiver, Location receiver) {  		if (from_receiver != null) {  			mBearingView.setText(String.format("%3.0f°", from_receiver.bearing));  			mDistanceView.setText(String.format("%6.0f m", from_receiver.distance)); @@ -168,7 +171,8 @@ public class TabMap extends Fragment implements AltosDroidTab {  					mPolyline.setVisible(true);  				} -				if (state.state == AltosLib.ao_flight_pad) { +				if (!pad_set && state.pad_lat != AltosLib.MISSING) { +					pad_set = true;  					mPadMarker.setPosition(new LatLng(state.pad_lat, state.pad_lon));  					mPadMarker.setVisible(true);  				} @@ -194,5 +198,4 @@ public class TabMap extends Fragment implements AltosDroidTab {  		}  	} -  } diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TabPad.java b/altosdroid/src/org/altusmetrum/AltosDroid/TabPad.java index 175a41de..03b78b75 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/TabPad.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/TabPad.java @@ -29,7 +29,7 @@ import android.widget.ImageView;  import android.widget.TextView;  import android.location.Location; -public class TabPad extends Fragment implements AltosDroidTab { +public class TabPad extends AltosDroidTab {  	AltosDroid mAltosDroid;  	private TextView mBatteryVoltageView; @@ -101,7 +101,9 @@ public class TabPad extends Fragment implements AltosDroidTab {  		mAltosDroid = null;  	} -	public void update_ui(AltosState state, AltosGreatCircle from_receiver, Location receiver) { +	public String tab_name() { return "pad"; } + +	public void show(AltosState state, AltosGreatCircle from_receiver, Location receiver) {  		if (state != null) {  			mBatteryVoltageView.setText(AltosDroid.number("%4.2f V", state.battery_voltage));  			mBatteryLights.set(state.battery_voltage >= AltosLib.ao_battery_good, state.battery_voltage == AltosLib.MISSING); diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TabsAdapter.java b/altosdroid/src/org/altusmetrum/AltosDroid/TabsAdapter.java index a4758c37..1ac34f9d 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/TabsAdapter.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/TabsAdapter.java @@ -21,6 +21,7 @@ import java.util.ArrayList;  import android.content.Context;  import android.os.Bundle;  import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentTransaction;  import android.support.v4.app.FragmentActivity;  import android.support.v4.app.FragmentPagerAdapter;  import android.support.v4.view.ViewPager; @@ -28,8 +29,7 @@ import android.view.View;  import android.view.ViewGroup;  import android.widget.TabHost;  import android.widget.TabWidget; - - +import android.util.Log;  /**   * This is a helper class that implements the management of tabs and all @@ -48,11 +48,13 @@ public class TabsAdapter extends FragmentPagerAdapter  	private final TabHost mTabHost;  	private final ViewPager mViewPager;  	private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>(); +	private int position; -	static final class TabInfo { +	static class TabInfo {  		private final String tag;  		private final Class<?> clss;  		private final Bundle args; +		private Fragment fragment;  		TabInfo(String _tag, Class<?> _class, Bundle _args) {  			tag = _tag; @@ -104,11 +106,32 @@ public class TabsAdapter extends FragmentPagerAdapter  	@Override  	public Fragment getItem(int position) {  		TabInfo info = mTabs.get(position); -		return Fragment.instantiate(mContext, info.clss.getName(), info.args); +		Log.d(AltosDroid.TAG, String.format("TabsAdapter.getItem(%d)", position)); +		info.fragment = Fragment.instantiate(mContext, info.clss.getName(), info.args); +		return info.fragment; +	} + +	public Fragment currentItem() { +		TabInfo info = mTabs.get(position); +		return info.fragment;  	}  	public void onTabChanged(String tabId) { -		int position = mTabHost.getCurrentTab(); +		AltosDroidTab	prev_frag = (AltosDroidTab) mTabs.get(position).fragment; + +		position = mTabHost.getCurrentTab(); + +		AltosDroidTab	cur_frag = (AltosDroidTab) mTabs.get(position).fragment; + +		if (prev_frag != cur_frag) { +			if (prev_frag != null) { +				prev_frag.set_visible(false); +			} +		} +		if (cur_frag != null) { +			cur_frag.set_visible(true); +		} +		Log.d(AltosDroid.TAG, String.format("TabsAdapter.onTabChanged(%s) = %d", tabId, position));  		mViewPager.setCurrentItem(position);  	}  | 
