我正在使用 Fragments,当我快速按下后退按钮时,应用程序崩溃了。它随机发生

Posted

技术标签:

【中文标题】我正在使用 Fragments,当我快速按下后退按钮时,应用程序崩溃了。它随机发生【英文标题】:I'm using Fragments and when I press the back button really fast the app crashes. It happens randomly 【发布时间】:2018-07-04 06:18:16 【问题描述】:

我正在使用 Fragments,当我快速按下后退按钮时,android 应用程序崩溃了。它是随机发生的,这里是java代码:

public class PlayerFragment extends Fragment 
    List<County> feeds;
    String action = "counties";
    private static MediaPlayer mMediaPlayer;

    TextView descr;
    TextView feed_id;
    TextView status;
    TextView listeners;
    TextView genre;
    TextView bitrate;

    private static Button switchButton;

    private AdView mAdView;
    InterstitialAd mInterstitialAd;

    public PlayerFragment() 
        // Required empty public constructor
    

    @Override
    public void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);

    

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) 
        View rootView = inflater.inflate(R.layout.fragment_player, container, false);
        //view called and initialized
        initView(rootView);
        updateView();
        AdRequest adRequest = new AdRequest.Builder()
                .build();
        mAdView.loadAd(adRequest);

        // set the ad unit ID
        mInterstitialAd.setAdUnitId(getString(R.string.interstitial_full_screen));

        // Load ads into Interstitial Ads
        mInterstitialAd.loadAd(adRequest);

        mInterstitialAd.setAdListener(new AdListener() 
            public void onAdLoaded() 
                showInterstitial();
            
        );

        final Retrofit.Builder builder = new Retrofit.Builder()
                .baseUrl(RadioApiClient.BASE_URL)
                .addConverterFactory(GsonConverterFactory.create());
        Retrofit retrofit = builder.build();

        RadioApiClient client = retrofit.create(RadioApiClient.class);

        Call<Counties> call = client.getCounties(action,
                BrowseStateFragment.stateId,
                RadioApiClient.JSON_RESPONSE,
                RadioApiClient.API_KEY);
        Log.d("Accessing url", client.getCounties(action, BrowseStateFragment.stateId,
                RadioApiClient.JSON_RESPONSE,
                RadioApiClient.API_KEY).request().url().toString());
        call.enqueue(new Callback<Counties>() 

            @Override
            public void onResponse(Call<Counties> call, Response<Counties> response) 


                feeds = response.body().getCounties();

                AudioManager amanager = (AudioManager) getActivity().getSystemService(Context.AUDIO_SERVICE);
                int maxVolume = amanager.getStreamMaxVolume(AudioManager.STREAM_ALARM);
                amanager.setStreamVolume(AudioManager.STREAM_ALARM, maxVolume, 0);
                mMediaPlayer = new MediaPlayer();
                mMediaPlayer.setAudiostreamType(AudioManager.STREAM_MUSIC);
                mMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() 
                    @Override
                    public void onPrepared(MediaPlayer mp) 
                        togglePlayPause();
                    
                );

                String station = BrowseFeedsFragment.station;
                Toast.makeText(getActivity(), "Setting radio", Toast.LENGTH_LONG).show();
                if (mMediaPlayer.isPlaying()) 
                    mMediaPlayer.stop();
                    Toast.makeText(getActivity(), "stopping radio", Toast.LENGTH_LONG).show();

                    mMediaPlayer.reset();
                    Toast.makeText(getActivity(), "resetting radio", Toast.LENGTH_LONG).show();
                
                try 
                    Toast.makeText(getActivity(), "Trying to play ", Toast.LENGTH_LONG).show();
                    mMediaPlayer.setDataSource(station);
                    mMediaPlayer.prepareAsync();
                    mMediaPlayer.start();
                    showInterstitial();
                    Toast.makeText(getActivity(), "playing", Toast.LENGTH_LONG).show();
                 catch (IOException e) 
                    e.printStackTrace();
                

            

            @Override
            public void onFailure(Call<Counties> call, Throwable t) 
                Log.d("no success", "" + "onfailure");
                t.printStackTrace();
            
        );
        // Inflate the layout for this fragment
        return rootView;
    

    @Override
    public void onAttach(Activity activity) 
        super.onAttach(activity);
    

    @Override
    public void onPause() 
        if (mAdView != null) 
            mAdView.pause();
        
        super.onPause();
    

    @Override
    public void onResume() 
        super.onResume();
        if (mAdView != null) 
            mAdView.resume();
            showInterstitial();
        
    

    @Override
    public void onDestroy() 
        if (mAdView != null) 
            mAdView.destroy();
        
        super.onDestroy();
    

    @Override
    public void onDetach() 
        super.onDetach();
    

    private void togglePlayPause() 
        if (mMediaPlayer.isPlaying()) 
            mMediaPlayer.pause();
            switchButton.setText("Play");
            Toast.makeText(getActivity(), "Paused", Toast.LENGTH_LONG).show();

         else 
            mMediaPlayer.start();
            switchButton.setText("Pause");


            Toast.makeText(getActivity(), "Playing", Toast.LENGTH_LONG).show();

        
    

    private void showInterstitial() 
        if (mInterstitialAd.isLoaded()) 
            mInterstitialAd.show();
        
    

    public void initView(View rootView) 
        descr = (TextView) rootView.findViewById(R.id.descr);
        feed_id = (TextView) rootView.findViewById(R.id.feed_id);
        status = (TextView) rootView.findViewById(R.id.status);
        listeners = (TextView) rootView.findViewById(R.id.listeners);
        genre = (TextView) rootView.findViewById(R.id.genre);
        bitrate = (TextView) rootView.findViewById(R.id.bitrate);
        switchButton = (Button) rootView.findViewById(R.id.switchButton);
        mAdView = (AdView) rootView.findViewById(R.id.adView);
        mInterstitialAd = new InterstitialAd(getActivity());

    

    public void updateView() 
        //update views

        descr.setText("Description: " + BrowseFeedsFragment.descr);
        feed_id.setText("Feed Id: " + BrowseFeedsFragment.feed_id);

        if (BrowseFeedsFragment.status == "1") 
            status.setText("Status: " + "Live Streaming Active");
         else 
            status.setText("Status: " + "Live Streaming Offline");
        

        listeners.setText("Listerners: " + BrowseFeedsFragment.listeners);
        genre.setText("Genre: " + BrowseFeedsFragment.genre);
        bitrate.setText("Bitrate: " + BrowseFeedsFragment.bitrate + "KBPS");

        Log.d("Success", "" + "Update Success");

        //event handling
        switchButton.setOnClickListener(new View.OnClickListener() 
            @Override
            public void onClick(View view) 
                togglePlayPause();
            
        );

    

我收到的错误消息是这样的:

> FATAL EXCEPTION: main
>     Process: com.kwawannan.policedispatchlivescanner, PID: 27704
>     java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.content.Context.getPackageName()' on a null
> object reference
>          at android.widget.Toast.<init>(Toast.java:103)
>          at android.widget.Toast.makeText(Toast.java:256)
>          at com.kwawannan.policedispatchlivescanner.activity.PlayerFragment.togglePlayPause(PlayerFragment.java:208)
>          at com.kwawannan.policedispatchlivescanner.activity.PlayerFragment.access$200(PlayerFragment.java:36)
>          at com.kwawannan.policedispatchlivescanner.activity.PlayerFragment$2$1.onPrepared(PlayerFragment.java:123)
>          at android.media.MediaPlayer$EventHandler.handleMessage(MediaPlayer.java:2872)
>          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)

【问题讨论】:

可能是它的副本 - ***.com/questions/28515049/… 你在某处展示了无效上下文的吐司 我应该使用什么上下文? 【参考方案1】:

这是因为onResponse 在片段被销毁并与活动分离后被调用。

正确的解决方案是在片段被销毁时取消或处理调用:

onDestroyView中调用call.cancel()call.dispose方法

【讨论】:

如何使用 call.cancel() ,调用在我的代码中是未知的 在 onCreateView 中创建调用 Call&lt;Counties&gt; call = client.getCountie ... 只需使其成为类成员,这样您就可以在 destroy 中访问它 调用 call.cancel() 后仍然会发生 'java.lang.String android.content.Context.getPackageName()' 在空对象引用上,在 com.kwawannan.policedispatchlivescanner.activity.PlayerFragment.togglePlayPause(PlayerFragment.java:210) 在com.kwawannan.policedispatchlivescanner.activity.PlayerFragment.access$200(PlayerFragment.java:36) at com.kwawannan.policedispatchlivescanner.activity.PlayerFragment$2$1.onPrepared(PlayerFragment.java:124)【参考方案2】:

如显示错误代码。

com.kwawannan.policedispatchlivescanner, PID: 27704 java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.content.Context.getPackageName()' on a null object reference at android.widget.Toast.(Toast.java:103)

你应该使用 getContext() 而不是 getActivity();喜欢

Toast.makeText(getContext(), "msg text", Toast.LENGTH_LONG).show();

【讨论】:

【参考方案3】:

像下面这样改变你的切换方法:

private void togglePlayPause() 
        Activity activity = getActivity();
        if (mMediaPlayer!=null && activity!=null) 
            if (mMediaPlayer.isPlaying()) 
                mMediaPlayer.pause();
                switchButton.setText("Play");
                Toast.makeText(activity, "Paused", Toast.LENGTH_LONG).show();    
             else 
                mMediaPlayer.start();
                switchButton.setText("Pause");
                Toast.makeText(activity, "Playing", Toast.LENGTH_LONG).show();
            
        
    

希望对你有帮助。

【讨论】:

以上是关于我正在使用 Fragments,当我快速按下后退按钮时,应用程序崩溃了。它随机发生的主要内容,如果未能解决你的问题,请参考以下文章

当Webview方向更改然后按下后退按钮时,应用程序崩溃

如何为Android Fragments(Tabs Activity)实现onBackPressed

Windows 10 UWP 应用程序 - 后退按钮仅在第二次按下时有效

jQuery地址:证明用户正在按下前进按钮而不是后退按钮

如何确定后退按钮按下

在颤动中打开对话框时检测返回按钮按下