我试图让我的应用程序显示连续值,即使是通过活动破坏和娱乐。我使用后台线程来维护FPS,基本上只是将消息发送给处理程序。当销毁并重新创建活动时,将创建一个新的处理程序并将其发送到后台线程的新实例。但是,当收到消息时,它们似乎正由原始处理程序接收,在“已销毁”活动中运行。如果有比我更有经验的人能够参与其中,我真的很感激!
我的代码(我知道它不止一点,但几乎所有相关内容都发生在onCreate上):
public class MainActivity extends FragmentActivity {
final static int UPDATE_DISPLAY = 1;
//View Pager declarations
private static final int NUM_PAGES = 4; //Number of viewPager pages
private ViewPager mPager;
private ScreenSlidePagerAdapter mPagerAdapter;
private MainThread thread;
Fragment[] fragmentMap = new Fragment[NUM_PAGES];
//End view pager declarations
globalData gd;
private Handler handler = new Handler()
{
@Override
public void handleMessage(Message msg)
{
//TESTING-------------
System.out.println("Received message from background thread.");
System.out.println("Handler receiving message is: "+this.toString());
System.out.println("Handler is running in activity: "+MainActivity.this.toString());
//---------------
if (msg.what == UPDATE_DISPLAY){
((TextView)findViewById(R.id.totalGas)).
setText("Gas: "+UnitValuePair.convertNumberToString(gd.getGasOwned()));
((TextView)findViewById(R.id.totalRock)).
setText("Rock: "+UnitValuePair.convertNumberToString(gd.getRockOwned()));
((TextView)findViewById(R.id.totalMetal)).
setText("Metal: "+UnitValuePair.convertNumberToString(gd.getMetalOwned()));
}
super.handleMessage(msg);
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
System.out.println("CREATING MainActivity");
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_screen_slide);
Button resetButton = (Button)findViewById(R.id.resetButton);
resetButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
resetData();
}
});
//Instantiate ViewPager and PagerAdapter
mPager = (ViewPager)findViewById(R.id.pager);
mPagerAdapter = new ScreenSlidePagerAdapter(getSupportFragmentManager());
mPager.setAdapter(mPagerAdapter);
mPager.setOffscreenPageLimit(5);
//Attach tablayout to view pager
TabLayout tabLayout = (TabLayout) findViewById(R.id.sliding_tabs);
tabLayout.setupWithViewPager(mPager);
//Init variable
gd = globalData.getInstance();
//Check if new game, and if so, init all base and actual values
Context context = getApplicationContext();
SharedPreferences sharedPref = context.getSharedPreferences(
getString(R.string.preference_file_key), Context.MODE_PRIVATE);
//If first start, then init vals and mark that it has been started in shared preferences
boolean startedBefore = sharedPref.getBoolean("startedBefore", false);
Log.d("TEST", "Value of startedBefore boolean is:" + Boolean.toString(startedBefore));
if (!startedBefore)
{
gd.initVals();
gd.storeData();
gd.setNewGame(false);
SharedPreferences.Editor editor = sharedPref.edit();
editor.putBoolean("startedBefore", true);
editor.commit();
}
else
{
System.out.println("Restoring data");
gd.restoreData();
}
//TESTING---------
System.out.println("Handler seen by activity is: "+handler.toString());
System.out.println("New Activity is : "+this.toString());
//--------------------
//Start main update thread
thread = new MainThread((ViewGroup)findViewById(R.id.mainContainer), gd, handler, getApplicationContext());
thread.setRunning(true);
thread.start();
}
@Override
public void onPause()
{
System.out.println("PAUSING MainActivity");
super.onPause();
gd.storeData();
}
@Override
public void onResume()
{
super.onResume();
System.out.println("RESUMING MainActivity");
}
@Override
public void onBackPressed(){
if (mPager.getCurrentItem() == 0){
//If the user is currently looking at the first step, allow the system to handle
//back button. Calls finish() on activity and pops the back stack
super.onBackPressed();
} else {
mPager.setCurrentItem(mPager.getCurrentItem() - 1);
}
}
public class ScreenSlidePagerAdapter extends FragmentStatePagerAdapter
{
public ScreenSlidePagerAdapter(FragmentManager fm)
{
super(fm);
}
@Override
public Fragment getItem (int position)
{
switch (position) {
case 0:
CreationFragment newFragment0 = CreationFragment.newInstance(0);
fragmentMap[0] = newFragment0;
return newFragment0;
case 1:
UniverseFragment newFragment1 = UniverseFragment.newInstance(1);
fragmentMap[1] = newFragment1;
return newFragment1;
default:
return ScreenSlidePageFragment.create(position);
}
}
@Override
//Provides the titles of the fragments for use in tabLayout
public CharSequence getPageTitle(int position) {
String title=" ";
switch (position){
case 0:
title="Create";
break;
case 1:
title="Universe";
break;
case 2:
title="Upgrades";
break;
case 3:
title="Stats";
break;
}
return title;
}
@Override
public int getCount()
{
return NUM_PAGES;
}
}
@Override
protected void onDestroy(){
System.out.println("DESTROYING MainActivity");
//handler = null;
super.onDestroy();
}
public void resetData()
{
gd.initVals();
gd.setVisibilityChangedDisplay(true);
gd.setVisibilityChangedInv(true);
gd.setChangedDisplay(true);
gd.setChangedInv(true);
}
}
logcat:
原始处理程序6402d8e开始在活动108d9af中运行。活动暂停,销毁并重新创建为活动3112cf7。创建一个新的处理程序70420f6并将其发送到新的后台线程。后台线程开始发送消息,并且它们被接收,但接收它们的处理程序说它是原始的6402d8e,仍然在活动108d9af中运行!
04-09 20:17:41.471 29339-29339/com.kessler.alexi.stellargrowth I/System.out: Received message from background thread.
04-09 20:17:41.471 29339-29339/com.kessler.alexi.stellargrowth I/System.out: Handler receiving message is: Handler (com.kessler.alexi.stellargrowth.MainActivity$1) {6402d8e}
04-09 20:17:41.471 29339-29339/com.kessler.alexi.stellargrowth I/System.out: Handler is running in activity: com.kessler.alexi.stellargrowth.MainActivity@108d9af
04-09 20:17:41.502 29339-29339/com.kessler.alexi.stellargrowth I/System.out: PAUSING MainActivity
04-09 20:17:41.502 29339-29339/com.kessler.alexi.stellargrowth D/TEST: Storing data
04-09 20:17:41.741 29339-29339/com.kessler.alexi.stellargrowth I/System.out: DESTROYING MainActivity
04-09 20:17:41.759 29339-29339/com.kessler.alexi.stellargrowth I/System.out: CREATING MainActivity
04-09 20:17:41.759 29339-29339/com.kessler.alexi.stellargrowth W/FragmentManager: moveToState: Fragment state for CreationFragment{a0042e2 #1 id=0x7f0d006d} not updated inline; expected state 1 found 0
04-09 20:17:41.759 29339-29339/com.kessler.alexi.stellargrowth W/FragmentManager: moveToState: Fragment state for UniverseFragment{66e2681 #2 id=0x7f0d006d} not updated inline; expected state 1 found 0
04-09 20:17:41.775 29339-29339/com.kessler.alexi.stellargrowth D/TEST: Value of startedBefore boolean is:true
04-09 20:17:41.775 29339-29339/com.kessler.alexi.stellargrowth I/System.out: Restoring data
04-09 20:17:41.775 29339-29339/com.kessler.alexi.stellargrowth D/TEST: Retrieving data
04-09 20:17:41.775 29339-29339/com.kessler.alexi.stellargrowth I/System.out: Handler seen by activity is: Handler (com.kessler.alexi.stellargrowth.MainActivity$1) {70420f6}
04-09 20:17:41.775 29339-29339/com.kessler.alexi.stellargrowth I/System.out: New Activity is : com.kessler.alexi.stellargrowth.MainActivity@3112cf7
04-09 20:17:41.775 29339-29339/com.kessler.alexi.stellargrowth I/System.out: New thread created. Handler seen by thread is: Handler (com.kessler.alexi.stellargrowth.MainActivity$1) {70420f6}
04-09 20:17:41.805 29339-29339/com.kessler.alexi.stellargrowth I/System.out: RESUMING MainActivity
04-09 20:17:41.811 29339-29339/com.kessler.alexi.stellargrowth I/System.out: Received message from background thread.
04-09 20:17:41.811 29339-29339/com.kessler.alexi.stellargrowth I/System.out: Handler receiving message is: Handler (com.kessler.alexi.stellargrowth.MainActivity$1) {6402d8e}
04-09 20:17:41.811 29339-29339/com.kessler.alexi.stellargrowth I/System.out: Handler is running in activity: com.kessler.alexi.stellargrowth.MainActivity@108d9af
---- UPDATE ------ 新活动启动新线程,但发送消息的那个具有应该被销毁的旧ID的ID
04-10 10:43:41.149 19846-19846/com.kessler.alexi.stellargrowth I/System.out: New Activity is : com.kessler.alexi.stellargrowth.MainActivity@49e83d5
04-10 10:43:41.149 19846-19846/com.kessler.alexi.stellargrowth I/System.out: New thread created with id: 23410
04-10 10:43:41.149 19846-19846/com.kessler.alexi.stellargrowth I/System.out: Handler seen by new thread is: Handler (com.kessler.alexi.stellargrowth.MainActivity$1) {cf3308c}
04-10 10:43:41.149 19846-19846/com.kessler.alexi.stellargrowth I/System.out: Starting thread with id: 23410
04-10 10:43:41.180 19846-19878/com.kessler.alexi.stellargrowth I/System.out: Thread sending message is: 23405
04-10 10:43:41.188 19846-19846/com.kessler.alexi.stellargrowth I/System.out: RESUMING MainActivity
04-10 10:43:41.194 19846-19846/com.kessler.alexi.stellargrowth I/System.out: Received message from background thread.
04-10 10:43:41.194 19846-19846/com.kessler.alexi.stellargrowth I/System.out: Handler receiving message is: Handler (com.kessler.alexi.stellargrowth.MainActivity$1) {6402d8e}
04-10 10:43:41.194 19846-19846/com.kessler.alexi.stellargrowth I/System.out: Handler is running in activity: com.kessler.alexi.stellargrowth.MainActivity@108d9af
----- ------ ANSWER 事实证明,这只是将onDestroy更改为
的问题@Override
protected void onDestroy(){
System.out.println("DESTROYING MainActivity");
thread.setRunning(false);
super.onDestroy();
}
线程运行代码(如下所示)获取了锁,基本上从不关闭,因为布尔运行没有自动更改。当新线程启动时,它尝试获取锁定,失败,并且旧的线程再次启动。
@Override
public void run() {
System.out.println("Thread "+this.getId()+" started.");
if (MainThread.lock.tryLock()) {
System.out.println("Thread "+this.getId()+" acquired lock");
try {
long tickCount = 0L;
while (running) {
tickCount++;
controlFPS(tickCount);
update();
}
} finally {
MainThread.lock.unlock();
}
}
}
答案 0 :(得分:0)
将线程声明为类中的私有字段,以便类中的所有方法都可以访问它,然后:
在onDestroy()方法
使用
thread.Abort()