天文台表和碎片,旋转后恢复状态



我试过Android:旋转后如何恢复停止的计时器的状态?和片段恢复方向更改的状态,但它们不适用于我,因为它们要么不起作用,要么我正在使用片段。

此外,似乎任何对天文台表的引用似乎都会引发应用程序崩溃。

错误:

java.lang.RuntimeException: Unable to start activity ComponentInfo{com.elliot_labs.timetracker/com.elliot_labs.timetracker.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.Chronometer.setBase(long)' on a null object reference
                      at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2665)
                      at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2726)
                      at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:4519)
                      at android.app.ActivityThread.-wrap19(ActivityThread.java)
                      at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1483)
                      at android.os.Handler.dispatchMessage(Handler.java:102)
                      at android.os.Looper.loop(Looper.java:154)
                      at android.app.ActivityThread.main(ActivityThread.java:6119)
                      at java.lang.reflect.Method.invoke(Native Method)
                      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
                   Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.Chronometer.setBase(long)' on a null object reference
                      at com.elliot_labs.timetracker.MainFragment.onCreate(MainFragment.java:95)
                      at android.support.v4.app.Fragment.performCreate(Fragment.java:2172)
                      at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1243)
                      at android.support.v4.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1523)
                      at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1585)
                      at android.support.v4.app.FragmentManagerImpl.dispatchCreate(FragmentManager.java:2827)
                      at android.support.v4.app.FragmentController.dispatchCreate(FragmentController.java:190)
                      at android.support.v4.app.FragmentActivity.onCreate(FragmentActivity.java:353)
                      at android.support.v7.app.AppCompatActivity.onCreate(AppCompatActivity.java:88)
                      at com.elliot_labs.timetracker.MainActivity.onCreate(MainActivity.java:30)
                      at android.app.Activity.performCreate(Activity.java:6679)
                      at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1118)
                      at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2618)
                      at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2726) 
                      at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:4519) 
                      at android.app.ActivityThread.-wrap19(ActivityThread.java) 
                      at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1483) 
                      at android.os.Handler.dispatchMessage(Handler.java:102) 
                      at android.os.Looper.loop(Looper.java:154) 
                      at android.app.ActivityThread.main(ActivityThread.java:6119) 
                      at java.lang.reflect.Method.invoke(Native Method) 
                      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886) 
                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776) 
Application terminated.

代码(片段.java):

package com.elliot_labs.timetracker;

import android.content.Context;
import android.os.Bundle;
import android.os.SystemClock;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Chronometer;
import android.widget.Toast;

/**
 * A simple {@link Fragment} subclass.
 */
public class MainFragment extends Fragment implements OnClickListener {
    Button toggleButton;
    Button resetButton;
    Chronometer chronometer;
    long timeWhenStopped = 0;
    boolean currentlyTiming = false;
    public MainFragment() {
        // Required empty public constructor
    }
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        View v = inflater.inflate(R.layout.fragment_main, container, false);
        toggleButton = (Button) v.findViewById(R.id.buttonToggleChronometer);
        resetButton = (Button) v.findViewById(R.id.buttonReset);
        chronometer = (Chronometer) v.findViewById(R.id.mainChronometer);
        toggleButton.setOnClickListener(this);
        resetButton.setOnClickListener(this);
        return v;
    }
    public void toggleChronometer(){
        if(!currentlyTiming){
            chronometer.setBase(SystemClock.elapsedRealtime() + timeWhenStopped);
            chronometer.start();
            toggleButton.setText("Stop");
            currentlyTiming = true;
        } else {
            timeWhenStopped = chronometer.getBase() - SystemClock.elapsedRealtime();
            chronometer.stop();
            toggleButton.setText("Start");
            currentlyTiming = false;
        }
    }
    public void resetChronometer(){
        timeWhenStopped = 0;
        chronometer.setBase(SystemClock.elapsedRealtime());
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.buttonToggleChronometer:
                toggleChronometer();
                break;
            case R.id.buttonReset:
                resetChronometer();
                break;
        }
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        // Save myVar's value in saveInstanceState bundle
        outState.putLong("time", chronometer.getBase());
        outState.putBoolean("isTiming", currentlyTiming);
        super.onSaveInstanceState(outState);
    }
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // savedInstanceState is the bundle in which we stored myVar in onSaveInstanceState() method above
        // savedInstanceState == null means that activity is being created a first time
        if (savedInstanceState != null) {
            chronometer.setBase(savedInstanceState.getLong("time"));
            if (savedInstanceState.getBoolean("isTiming")) {
                chronometer.start();
                currentlyTiming = savedInstanceState.getBoolean("isTiming");
            }
        }
    }
}

代码(mainActivity.java):

package com.elliot_labs.timetracker;
import android.os.Bundle;
import android.support.design.widget.NavigationView;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.MenuItem;
public class MainActivity extends AppCompatActivity
        implements NavigationView.OnNavigationItemSelectedListener {
    NavigationView navigationView = null;
    Toolbar toolbar = null;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // Starts the main fragment
        MainFragment fragment = new MainFragment();
        android.support.v4.app.FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
        fragmentTransaction.replace(R.id.fragment_container, fragment);
        fragmentTransaction.commit();
        toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        navigationView = (NavigationView) findViewById(R.id.nav_view);
        navigationView.setNavigationItemSelectedListener(this);
        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
                this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
        drawer.setDrawerListener(toggle);
        toggle.syncState();
    }
    @Override
    public void onBackPressed() {
        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        if (drawer.isDrawerOpen(GravityCompat.START)) {
            drawer.closeDrawer(GravityCompat.START);
        } else {
            super.onBackPressed();
        }
    }

    @SuppressWarnings("StatementWithEmptyBody")
    @Override
    public boolean onNavigationItemSelected(MenuItem item) {
        // Handle navigation view item clicks here.
        int id = item.getItemId();
        if (id == R.id.nav_timer) {
            MainFragment fragment = new MainFragment();
            android.support.v4.app.FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
            fragmentTransaction.replace(R.id.fragment_container, fragment);
            fragmentTransaction.commit();
        } else if (id == R.id.nav_categories) {
            CategoryFragment fragment = new CategoryFragment();
            android.support.v4.app.FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
            fragmentTransaction.replace(R.id.fragment_container, fragment);
            fragmentTransaction.commit();
        } else if (id == R.id.nav_slideshow) {
        } else if (id == R.id.nav_manage) {
        } else if (id == R.id.nav_settings) {
            SettingsFragment fragment = new SettingsFragment();
            android.support.v4.app.FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
            fragmentTransaction.replace(R.id.fragment_container, fragment);
            fragmentTransaction.commit();
        } else if (id == R.id.nav_feedback) {
        } else if (id == R.id.nav_help) {
        }
        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        drawer.closeDrawer(GravityCompat.START);
        return true;
    }
}

如何在旋转屏幕后恢复状态?

谢谢!

onCreate 在 onCreateView 之前调用,因此 chonometer 字段为空,只需在 onCreateView 中恢复计时器并删除 onCreate 中的代码即可。

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    View v = inflater.inflate(R.layout.fragment_main, container, false);
    toggleButton = (Button) v.findViewById(R.id.buttonToggleChronometer);
    resetButton = (Button) v.findViewById(R.id.buttonReset);
    chronometer = (Chronometer) v.findViewById(R.id.mainChronometer);
    toggleButton.setOnClickListener(this);
    resetButton.setOnClickListener(this);
    if (savedInstanceState != null) {
        chronometer.setBase(savedInstanceState.getLong("time"));
        if (savedInstanceState.getBoolean("isTiming")) {
            chronometer.start();
            currentlyTiming = savedInstanceState.getBoolean("isTiming");
        }
    }
    return v;
}

然后在您的活动中对片段进行条件化替换,如下所示:

if (savedInstanceState == null) {
    MainFragment fragment = new MainFragment();
    FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
    fragmentTransaction.replace(R.id.fragment_container, fragment);
    fragmentTransaction.commit();
}

最新更新