我正在编程一个调谐器。 调谐器是一个片段。 我的目标是当手机在横向和纵向模式之间切换时,保持调谐器运行。 因此,我使用onSaveInstanceState()保存实际状态,并使用onViewStateRestored()恢复它。 实际上效果很好。 但是我有一个大问题:重建片段时,onDestroy(),onCreateView()和onViewStateRestored()会再次执行。 这会导致崩溃。 任何想法如何解决?

在代码下方,请询问您是否需要更详细的代码:

public class TunerFragment extends BasicFragment
{
    //View Elemente
        public boolean controlButtonUnclicked = true;
        private static final String LOG_TAG = "FFTTEST";
        private final Semaphore bufferZugriff = new Semaphore(1, true);


        //Objecte zur Aufnahme
        private int channel_config = AudioFormat.CHANNEL_IN_MONO;
        private int format = AudioFormat.ENCODING_PCM_16BIT;
        private int sampleRate = 44100;
        private int bufferSize = AudioRecord.getMinBufferSize(sampleRate, channel_config, format)*8; // je größer der Buffer, desto genauer die FFT!!
        private AudioRecord audioInput = null; //new AudioRecord(AudioSource.MIC, sampleSize, channel_config, format, bufferSize);
        private short[] audioBuffer = new short[bufferSize];

        //Attribute zur Steuerung
        private Thread readingThread = null,writingThread=null;
        private boolean isRecording = false;




    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
    {
        View view;

        view = inflater.inflate(R.layout.fragment_tuner, container, false);

        TextView tv = (TextView) view.findViewById(R.id.textview_referencenote);

        SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this.getActivity());

        tv.setText(sharedPrefs.getString("value_a", "440"));

        Button mButton = (Button) view.findViewById(R.id.controlButton);
        mButton.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                onControlButton(v);
            }
        });
        return view;
    }

    @Override
    public void onDestroy() { 
        super.onDestroy();
        if(isRecording)
        {
            isRecording = false;
            while(this.readingThread.isAlive());

            try
            {
                audioInput.stop();
                audioInput.release();
            }
            catch (Exception e)
            {}
            while(this.writingThread.isAlive());

            audioInput= null;
            readingThread = null;
            writingThread = null;

        }
    }

    @Override
    public void onStop() {
        super.onStop();
        if(isRecording) 
        {
            isRecording = false;
            while(this.readingThread.isAlive());
            try
            {
                audioInput.stop();
                audioInput.release();
            }
            catch (Exception e)
            {}
            while(this.writingThread.isAlive());

            audioInput= null;
            readingThread = null;
            writingThread = null;

        }
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putBoolean("isRecording", isRecording); 
    }

    @Override
    public void onViewStateRestored (Bundle savedInstanceState) {
        super.onViewStateRestored (savedInstanceState);
        if(savedInstanceState!=null)    
        {
            if(savedInstanceState.getBoolean("isRecording"))
            {
                Button mPlayButton = (Button) getView().findViewById(R.id.controlButton);
                //Recorder starten
                controlButtonUnclicked = false;
                mPlayButton.setText("Stop");
                startRecording();
                isRecording = true;
            }
        }
    }

    public void onControlButton(View v)
    {
        //...


    }


    private void onPlay(boolean start) {
       //starts and stops the tuner, depending on the actual state

    }



    private void startRecording()
    {

        //prepares and starts the worker threads (Thread for reading the Mic.-buffer and Thread for processing the signal)
    }



    private int maxFrequenzToIndex (int MaxFreq)
    {
        return (MaxFreq * 1 * bufferSize) / (1 * sampleRate);
    }

    private void calculate()
    {
        while(isRecording)
        {
                //processing the signal ...



                //post result to main thread
                final String notennamef = notenname;
                final int differenzf=differenz;
                ((TextView) getView().findViewById(R.id.editNote)).post(new Runnable() {

                    @Override
                    public void run() {
                        try
                        {
                            TextView View = (TextView) getView().findViewById(R.id.editNote);

                            View.setText(""+notennamef); 

                            View = (TextView) getView().findViewById(R.id.editAbweichung);
                            View.setText(""+differenzf); 
                        }
                        catch (NullPointerException e)
                        {
                            System.out.println("Exception in calculate() -> run()");
                            System.out.println(e);
                        }
                    }
                });

            try
            {
                Thread.sleep(100); //Wie oft wird die Anzeige aktualisiert?
            }
            catch (InterruptedException e)
            {}
        }
        // restore neutral view
            ((TextView) getView().findViewById(R.id.editNote)).post(new Runnable() {

                @Override
                public void run() {
                    try
                     {
                            TextView View = (TextView) getView().findViewById(R.id.editNote);
                            View.setText("");



                            View = (TextView) getView().findViewById(R.id.editAbweichung);
                            View.setText("");
                     }
                     catch (NullPointerException e)
                     {
                         System.out.println("Exception in calculate() -> nach while");
                         System.out.println(e);
                     }
                }
            });
    }

    private int calculateCent(double referenz, double frequenz)
    {
        return (int) (1200*(Math.log(frequenz/referenz)/Math.log(2)));  // die Formel entspricht 1200*log2(frequenz/referenz)
    }

    private void readAudioToBuffer() 
    {
        while(isRecording)
        {

            try
            {
                bufferZugriff.acquire();
                audioInput.read(audioBuffer, 0,bufferSize);
                bufferZugriff.release();
            }
            catch (Exception e )
            {
                System.out.println("Fehler beim schreiben in den Audiobuffer");
            }

        }

     }


    private void stopRecording()
    {
        isRecording = false;
        try
        {
            audioInput.stop();
            audioInput.release();
        }
        catch (Exception e)
        {}
        audioInput= null;
        readingThread = null;
        writingThread = null;
        getView().findViewById(R.id.controlButton).setKeepScreenOn(false);
    }
}

===============>>#1 票数:6 已采纳

问题在于,当手机在横向和纵向模式之间切换时,将重新创建活动。

因此,您需要确保在活动重新创建时不要通过覆盖活动的onCreate方法来创建新片段,如下所示:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_layout);

    if (savedInstanceState == null) {
        FragmentManager manager = getSupportFragmentManager();
        FragmentTransaction transaction = manager.beginTransaction();

        Fragment fragment = new TunerFragment();
        transaction.add(R.id.fragment_container, fragment);
        transaction.commit();
    }
}

  ask by Benedikt Bock translate from so

未解决问题?本站智能推荐:

2回复

片段上的onstart()在android中被调用了两次

我有一个活动,其中有一个片段。 在片段的onStart()中,我有所有网络调用。当app来自后台时,onStart()被调用两次,所有网络都被调用了两次,我还观察到onCreate()仅被调用了一次,有人遇到了这样的问题。请帮帮我。 我的片段交易代码如下 提前致谢 !!!
1回复

Android片段OnCreateView调用了两次

我正在使用FragmentPagerAdapter和片段。 我的问题是,当我调用setCurrentItem时,正在加载的片段的OnCreateView方法被调用两次。 重要的是要注意,片段不会重新创建,只需恢复即可。 我迫不及待地想找到一个只能调用一次OnCreateView的解决方案。
2回复

手机重启后Android onCreate调用两次,使片段停止工作

我已经编写了一个Android应用程序,它在手机重启后立即启动(在5秒左右)启动时出现问题(崩溃)。 由于某种原因,OnCreate方法第二次被调用。 我认为这可能是问题所在,但经过研究,我发现android系统可能会在启动后回想起onCreate,因为它仍在启动系统服务 - 例如获取“MC
1回复

android:为什么FragmentActivity.onDestroy调用片段onCreateView

崩溃在下面 奇怪的是,片段onCreatView不是从Activity onCreate而是从onDestroy调用的。 在系统或某些第三方工具杀死应用程序后进入应用程序时,会发生这种情况。 有人遇到过这个吗? ********** ********** UPDATE 从
5回复

带有片段的Android mapview无法添加两次?

我使用Android兼容性类与黑客在这里找到的片段中使用mapviews: https : //github.com/petedoyle/android-support-v4-googlemaps 不幸的是,我发现如果mapfragment从活动中删除,然后重新读取,我得到“你只允许在Ma
1回复

片段开始两次

我有一个我使用片段的应用程序,但是每次我启动该应用程序时,每个活动(片段)都会启动两次。 我为此大声疾呼,但找不到答案。 有人能帮我吗? 这是我的主要FragmentActivity: 这是一个片段(我从一开始就开始):
2回复

使用片段两次调用onCreateView,onActivityCreated和onStart两次

是的,这个标题有几个问题,但是我找不到具体的答案(或者我错过了重点……)。 我有一个“经典” fragment应用程序:项目列表。 当我单击一个项目时,将出现对此项目的描述。 当我处于portrait mode ,仅显示项目列表。 当我点击一个项目,我代替fragment与项目的
5回复

片段onCreateView和onActivityCreated调用了两次

我正在使用Android 4.0 ICS和片段开发应用程序。 考虑ICS 4.0.3(API级别15)API的演示示例应用程序中的此修改示例: } 这是从运行此示例然后旋转手机检索到的输出: 我的问题是,为什么onCreateView和onActivityCreate
1回复

片段在屏幕旋转时被调用两次

我是Android新手,更改屏幕方向后会遇到此问题。 只要屏幕方向改变,该fragment就会被调用两次。 以下是我的代码示例。 我检查了其他帖子,但找不到答案。 有人指导我。
1回复

是否保证为片段调用onDestroy()?

我知道不能保证调用Activity onDestroy(...) 。 根据文件, 在某些情况下,系统会简单地杀死活动的托管进程,而不会在其中调用此方法(或任何其他方法),因此不应该使用它来做那些意图在进程消失后留下来的东西。 这也适用于碎片吗? 文档中没有任何内容,只是想确