私はいくつかのアニメーションロジックを使用する時計アプリを書いています。 onCreate()では、私のアプリアクティビティは、run()内のループでロジック処理を実行するThreadを継承するクラスのインスタンスを割り当てます。私は、キャンバスへの描画を管理するために、(LunarLanderの例によるが、コンテキスト修正スイッチを備えた)スレッド化されたSurfaceViewを使用している。Android:私のアプリケーションから離れたところでシステムが応答しなくなる
フォーカスがある限り、アプリは正常に動作します。私はonPause()の論理スレッドをsuspend()し、onDesroy()でonResume()とstop()をresume()して、ユーザーが離れたときにリソースを消費していないことを確認します。
このアプリはエミュレータで問題なく動作します。私は離れて、私は邪悪な効果がないように私はしばしばアプリに切り替えることができます。
しかし、物理ハードウェア上でAndroidで実行しているときに、アプリから離れて数回戻っても、システム全体が応答しなくなります。最終的には、電話機は上部のスリープ/電源スイッチを含むすべての入力を無視し、バッテリを取り外して再起動する必要があります。
テストとして、私はロジックスレッドの作成を無効にしましたが、レンダリングコードをすべて同じにして、アニメーションロジックの小さなビットを実行して、問題を解決しました。この論理処理スレッドは、システムにとって非常に悪いものでなければなりません。私はこれに新しいので、おそらくnoobの間違いをしています。
この問題をどのようにプロファイルできるかについての助けや助言をいただければ幸いです。
EDIT:アクティビティのソースを一覧表示します。私はリストを明確にすることを望んでスレッドに無関係な小塊を取り出しました。廃止され
public class EyesClockActivity extends Activity
implements SensorEventListener
{
// ---- options (shared preferences) ----
// snip, couple of booleans
// --------------------------------------------------------
private void LoadPreferences()
{
} // end EyesClockActivity.LoadPreferences()
// --------------------------------------------------------
private void SavePreferences()
{
} // end EyesClockActivity.SavePreferences()
// ========================================================
private class EyesClockActivityThread extends Thread
{
private long m_LastUpdateMilliSeconds;
private boolean m_running = false;
public void SetRunning(final boolean running)
{
// if restarting, don't want huge time leap
if ( (m_running == false)
&& (running == true))
{
m_LastUpdateMilliSeconds = System.currentTimeMillis();
}
m_running = running;
}
// ----------------------------------------------
public EyesClockActivityThread()
{
m_digits = new EyeDigit[4];
int index;
for (index = 0; index < m_digits.length; ++index)
{
m_digits[ index ] = new EyeDigit();
}
m_digits[0].SetCurrentDigit(0);
m_digits[1].SetCurrentDigit(0);
m_digits[2].SetCurrentDigit(0);
m_digits[3].SetCurrentDigit(0);
m_TestDigit.SetCurrentDigit(m_currentDigit);
m_LastUpdateMilliSeconds = System.currentTimeMillis();
m_lastDigitChangeMilliseconds = System.currentTimeMillis();
int minute = Calendar.getInstance().get(Calendar.MINUTE);
int hour = Calendar.getInstance().get(Calendar.HOUR_OF_DAY);
SetTime(hour, minute);
} // end EyesClockActivityThread constructor
// --------------------------------------------------------------------
// sets digits to display specified hour,minute
private void SetTime(final int hour, final int minute)
{
} // end method EyesClockActivityThread.SetTime()
// ----------------------------------------------
public void run()
{
while (true)
{
if (m_running)
{
final float updatesPerSecond = 30.0f;
final long milliSecondsBetweenUpdates = (long)((1.0f/updatesPerSecond) * 1000.0f);
long currentTimeMilliSeconds = System.currentTimeMillis();
// TODO sleep here instead of checking constantly
if ((currentTimeMilliSeconds - m_LastUpdateMilliSeconds) > milliSecondsBetweenUpdates)
{
int minute = Calendar.getInstance().get(Calendar.MINUTE);
// don't bother setting time unless minute has changed
if ((minute % 10) != m_digits[0].GetCurrentDigit())
{
int hour = Calendar.getInstance().get(Calendar.HOUR_OF_DAY);
SetTime(hour, minute);
}
float secondsSinceLastUpdate = (float)((currentTimeMilliSeconds - m_LastUpdateMilliSeconds)/1000.0);
for (EyeDigit digit : m_digits)
{
digit.Update(secondsSinceLastUpdate);
}
// global update routines
m_LastUpdateMilliSeconds = System.currentTimeMillis();
}
} // end if m_running
}
} // end EyesClockActivityThread.run()
} // end class EyesClockActivityThread
private EyesClockActivityThread m_EyesActivityThread;
private EyesClockSurfaceView m_EyesSurfaceView;
// ---- sensor interface ----
private SensorManager m_SensorManager;
private Sensor m_Accelerometer;
// -------------------------------------------------------------------------------
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState)
{
EyeDigit.InitDigitDescriptors();
m_EyesActivityThread = new EyesClockActivityThread();
// No Title bar
requestWindowFeature(Window.FEATURE_NO_TITLE);
m_EyesActivityThread.SetRunning(true);
m_EyesActivityThread.start();
LoadPreferences();
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
m_EyesSurfaceView = (EyesClockSurfaceView)findViewById(R.id.eyesclocksurfaceview);
Configuration config = getResources().getConfiguration();
m_EyesSurfaceView.SetOrientation(config.orientation);
m_EyesSurfaceView.SetDigits(m_EyesActivityThread.GetDigits());
m_SensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
m_Accelerometer = m_SensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
} // end method EyesClockActivity.onCreate()
// ----------------------------------------------
protected void onPause()
{
super.onPause();
// pause activity thread
m_EyesActivityThread.SetRunning(false);
m_EyesActivityThread.suspend();
// quit sensor listening
m_SensorManager.unregisterListener(this);
} // end method EyesClockActivity.onPause()
// ----------------------------------------------------
protected void onResume()
{
super.onResume();
// resume activity thread
m_EyesActivityThread.SetRunning(true);
m_EyesActivityThread.resume();
m_SensorManager.registerListener(this, m_Accelerometer, SensorManager.SENSOR_DELAY_NORMAL);
} // end method EyesClockActivity.onResume()
// ------------------------------------------------------
protected void onDestroy()
{
super.onDestroy();
m_EyesActivityThread.SetRunning(false);
m_EyesActivityThread.stop();
m_SensorManager.unregisterListener(this);
// quit sensor listening
m_SensorManager.unregisterListener(this);
} // end method EyesClockActivity.onDestroy()
// -------------------------------------------------------
public void onAccuracyChanged(Sensor sensor, int accuracy)
{
}
// ----------------------------------------------------
public void onSensorChanged(SensorEvent event)
{
if ( (event.values[0] > 15.0f)
|| (event.values[1] > 15.0f)
|| (event.values[2] > 15.0f))
{
m_EyesActivityThread.StartGoogleyEvent();
}
} // end method EyesClockActivity.onSensorChanged()
// ---- options menu ----
@Override
public boolean onCreateOptionsMenu(Menu menu)
{
// add cursor blink toggle item
menu.add(Menu.NONE, R.id.toggle_blink, Menu.NONE, R.string.string_blink_cursor);
if (GetTwelveHourDisplay())
{
menu.add(Menu.NONE, R.id.toggle_twelve_hour_display, Menu.NONE, R.string.string_24_hour_display);
}
else
{
menu.add(Menu.NONE, R.id.toggle_twelve_hour_display, Menu.NONE, R.string.string_12_hour_display);
}
return true;
}
@Override
public boolean onPrepareOptionsMenu(Menu menu)
{
super.onPrepareOptionsMenu(menu);
MenuItem displayItem = menu.getItem(1);
if (displayItem != null)
{
if (GetTwelveHourDisplay())
{
displayItem.setTitle(R.string.string_24_hour_display);
}
else
{
displayItem.setTitle(R.string.string_12_hour_display);
}
}
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item)
{
// Handle item selection
switch (item.getItemId())
{
case R.id.toggle_twelve_hour_display:
ToggleTwelveHourDisplay();
int minute = Calendar.getInstance().get(Calendar.MINUTE);
int hour = Calendar.getInstance().get(Calendar.HOUR_OF_DAY);
m_EyesActivityThread.SetTime(hour, minute);
SavePreferences();
return true;
case R.id.toggle_blink :
ToggleBlinkCursor();
SavePreferences();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
}
これまでに書いたことを示すことができますか? –
はい、私の元の投稿への編集として違反行為を追加しました。 。 – BHCPHX