我可以使用setTitle方法而不扩展Activity吗?

时间:2018-10-11 18:22:38

标签: java android

SettingsActivityPresenter.java生成此错误:无法解析方法'setTitle(java.lang.Integer)'

如果我将SettingsActivityPresenter扩展为Activity,则会得到:尝试在null对象引用上调用虚拟方法'android.content.res.Resources android.content.Context.getResources()'。 android.content.ContextWrapper.getResources(ContextWrapper.java:89)

是否有一种无需扩展setTitle就能使用Activity的方法?或者,如果我必须扩展Activity,该如何解决以上错误?

SettingsActivityPresenter.java:

package org.dolphinemu.dolphinemu.features.settings.ui;

import android.content.IntentFilter;
import android.os.Bundle;
import android.text.TextUtils;

import org.dolphinemu.dolphinemu.R;
import org.dolphinemu.dolphinemu.features.settings.model.Settings;
import org.dolphinemu.dolphinemu.utils.DirectoryInitialization;
import org.dolphinemu.dolphinemu.utils.DirectoryInitialization.DirectoryInitializationState;
import org.dolphinemu.dolphinemu.utils.DirectoryStateReceiver;
import org.dolphinemu.dolphinemu.utils.Log;

import java.util.HashMap;
import java.util.Map;

public final class SettingsActivityPresenter
{
  private static final String KEY_SHOULD_SAVE = "should_save";

  private SettingsActivityView mView;

  private Settings mSettings = new Settings();

  private int mStackCount;

  private boolean mShouldSave;

  private DirectoryStateReceiver directoryStateReceiver;

  private MenuTag menuTag;
  private String gameId;

	private static final Map<MenuTag, Integer> titles = new HashMap<>();

	static
	{
		titles.put(MenuTag.CONFIG, R.string.preferences_settings);
		titles.put(MenuTag.CONFIG_GENERAL, R.string.general_submenu);
		titles.put(MenuTag.CONFIG_INTERFACE, R.string.interface_submenu);
		titles.put(MenuTag.CONFIG_GAME_CUBE, R.string.gamecube_submenu);
		titles.put(MenuTag.CONFIG_WII, R.string.wii_submenu);
		titles.put(MenuTag.WIIMOTE, R.string.grid_menu_wiimote_settings);
		titles.put(MenuTag.WIIMOTE_EXTENSION, R.string.wiimote_extensions);
		titles.put(MenuTag.GCPAD_TYPE, R.string.grid_menu_gcpad_settings);
		titles.put(MenuTag.GRAPHICS, R.string.grid_menu_graphics_settings);
		titles.put(MenuTag.HACKS, R.string.hacks_submenu);
		titles.put(MenuTag.ENHANCEMENTS, R.string.enhancements_submenu);
		titles.put(MenuTag.STEREOSCOPY, R.string.stereoscopy_submenu);
		titles.put(MenuTag.GCPAD_1, R.string.controller_0);
		titles.put(MenuTag.GCPAD_2, R.string.controller_1);
		titles.put(MenuTag.GCPAD_3, R.string.controller_2);
		titles.put(MenuTag.GCPAD_4, R.string.controller_3);
		titles.put(MenuTag.WIIMOTE_1, R.string.wiimote_4);
		titles.put(MenuTag.WIIMOTE_2, R.string.wiimote_5);
		titles.put(MenuTag.WIIMOTE_3, R.string.wiimote_6);
		titles.put(MenuTag.WIIMOTE_4, R.string.wiimote_7);
		titles.put(MenuTag.WIIMOTE_EXTENSION_1, R.string.wiimote_extension_4);
		titles.put(MenuTag.WIIMOTE_EXTENSION_2, R.string.wiimote_extension_5);
		titles.put(MenuTag.WIIMOTE_EXTENSION_3, R.string.wiimote_extension_6);
		titles.put(MenuTag.WIIMOTE_EXTENSION_4, R.string.wiimote_extension_7);
	}

  SettingsActivityPresenter(SettingsActivityView view)
  {
    mView = view;
  }

  public void onCreate(Bundle savedInstanceState, MenuTag menuTag, String gameId)
  {
    if (savedInstanceState == null)
    {
      this.menuTag = menuTag;
      this.gameId = gameId;
    }
    else
    {
      mShouldSave = savedInstanceState.getBoolean(KEY_SHOULD_SAVE);
    }
  }

  public void onStart()
  {
    prepareDolphinDirectoriesIfNeeded();
  }

  private void loadSettingsUI()
  {
    if (mSettings.isEmpty())
    {
      if (!TextUtils.isEmpty(gameId))
      {
        mSettings.loadSettings(gameId, mView);
      }
      else
      {
        mSettings.loadSettings(mView);
      }
    }

    mView.showSettingsFragment(menuTag, null, false, gameId);
    mView.onSettingsFileLoaded(mSettings);
  }

  private void prepareDolphinDirectoriesIfNeeded()
  {
    if (DirectoryInitialization.areDolphinDirectoriesReady())
    {
      loadSettingsUI();
    }
    else
    {
      mView.showLoading();
      IntentFilter statusIntentFilter = new IntentFilter(
              DirectoryInitialization.BROADCAST_ACTION);

      directoryStateReceiver =
              new DirectoryStateReceiver(directoryInitializationState ->
              {
                if (directoryInitializationState ==
                        DirectoryInitializationState.DOLPHIN_DIRECTORIES_INITIALIZED)
                {
                  mView.hideLoading();
                  loadSettingsUI();
                }
                else if (directoryInitializationState ==
                        DirectoryInitializationState.EXTERNAL_STORAGE_PERMISSION_NEEDED)
                {
                  mView.showPermissionNeededHint();
                  mView.hideLoading();
                }
                else if (directoryInitializationState ==
                        DirectoryInitializationState.CANT_FIND_EXTERNAL_STORAGE)
                {
                  mView.showExternalStorageNotMountedHint();
                  mView.hideLoading();
                }
              });

      mView.startDirectoryInitializationService(directoryStateReceiver, statusIntentFilter);
    }
  }

  public void setSettings(Settings settings)
  {
    mSettings = settings;
  }

  public Settings getSettings()
  {
    return mSettings;
  }

  public void onStop(boolean finishing)
  {
    if (directoryStateReceiver != null)
    {
      mView.stopListeningToDirectoryInitializationService(directoryStateReceiver);
      directoryStateReceiver = null;
    }

    if (mSettings != null && finishing && mShouldSave)
    {
      Log.debug("[SettingsActivity] Settings activity stopping. Saving settings to INI...");
      mSettings.saveSettings(mView);
    }
  }

  public void addToStack()
  {
    mStackCount++;
  }

  public void onBackPressed()
  {
    if (mStackCount > 0)
    {
      mView.popBackStack();
      mStackCount--;
    }
    else
    {
      mView.finish();
    }

		if (titles.containsKey(menuTag))
		{
			setTitle(titles.get(menuTag));
		}
  }

  public boolean handleOptionsItem(int itemId)
  {
    switch (itemId)
    {
      case R.id.menu_save_exit:
        mView.finish();
        return true;
    }

    return false;
  }

  public void onSettingChanged()
  {
    mShouldSave = true;
  }

  public void saveState(Bundle outState)
  {
    outState.putBoolean(KEY_SHOULD_SAVE, mShouldSave);
  }

  public void onGcPadSettingChanged(MenuTag key, int value)
  {
    if (value != 0) // Not disabled
    {
      Bundle bundle = new Bundle();
      bundle.putInt(SettingsFragmentPresenter.ARG_CONTROLLER_TYPE, value / 6);
      mView.showSettingsFragment(key, bundle, true, gameId);
    }
  }

  public void onWiimoteSettingChanged(MenuTag menuTag, int value)
  {
    switch (value)
    {
      case 1:
        mView.showSettingsFragment(menuTag, null, true, gameId);
        break;

      case 2:
        mView.showToastMessage("Please make sure Continuous Scanning is enabled in Core Settings.");
        break;
    }
  }

  public void onExtensionSettingChanged(MenuTag menuTag, int value)
  {
    if (value != 0) // None
    {
      Bundle bundle = new Bundle();
      bundle.putInt(SettingsFragmentPresenter.ARG_CONTROLLER_TYPE, value);
      mView.showSettingsFragment(menuTag, bundle, true, gameId);
    }
  }
}

SettingsActivity.java:

package org.dolphinemu.dolphinemu.features.settings.ui;

import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.provider.Settings;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v7.app.AppCompatActivity;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.widget.Toast;

import org.dolphinemu.dolphinemu.R;
import org.dolphinemu.dolphinemu.utils.DirectoryInitialization;
import org.dolphinemu.dolphinemu.utils.DirectoryStateReceiver;

import java.util.HashMap;
import java.util.Map;

public final class SettingsActivity extends AppCompatActivity implements SettingsActivityView
{
  private static final String ARG_MENU_TAG = "menu_tag";
  private static final String ARG_GAME_ID = "game_id";
  private static final String FRAGMENT_TAG = "settings";
  private SettingsActivityPresenter mPresenter = new SettingsActivityPresenter(this);

  private ProgressDialog dialog;

  private static final Map<MenuTag, Integer> titles = new HashMap<>();

  static
  {
    titles.put(MenuTag.CONFIG, R.string.preferences_settings);
    titles.put(MenuTag.CONFIG_GENERAL, R.string.general_submenu);
    titles.put(MenuTag.CONFIG_INTERFACE, R.string.interface_submenu);
    titles.put(MenuTag.CONFIG_GAME_CUBE, R.string.gamecube_submenu);
    titles.put(MenuTag.CONFIG_WII, R.string.wii_submenu);
    titles.put(MenuTag.WIIMOTE, R.string.grid_menu_wiimote_settings);
    titles.put(MenuTag.WIIMOTE_EXTENSION, R.string.wiimote_extensions);
    titles.put(MenuTag.GCPAD_TYPE, R.string.grid_menu_gcpad_settings);
    titles.put(MenuTag.GRAPHICS, R.string.grid_menu_graphics_settings);
    titles.put(MenuTag.HACKS, R.string.hacks_submenu);
    titles.put(MenuTag.ENHANCEMENTS, R.string.enhancements_submenu);
    titles.put(MenuTag.STEREOSCOPY, R.string.stereoscopy_submenu);
    titles.put(MenuTag.GCPAD_1, R.string.controller_0);
    titles.put(MenuTag.GCPAD_2, R.string.controller_1);
    titles.put(MenuTag.GCPAD_3, R.string.controller_2);
    titles.put(MenuTag.GCPAD_4, R.string.controller_3);
    titles.put(MenuTag.WIIMOTE_1, R.string.wiimote_4);
    titles.put(MenuTag.WIIMOTE_2, R.string.wiimote_5);
    titles.put(MenuTag.WIIMOTE_3, R.string.wiimote_6);
    titles.put(MenuTag.WIIMOTE_4, R.string.wiimote_7);
    titles.put(MenuTag.WIIMOTE_EXTENSION_1, R.string.wiimote_extension_4);
    titles.put(MenuTag.WIIMOTE_EXTENSION_2, R.string.wiimote_extension_5);
    titles.put(MenuTag.WIIMOTE_EXTENSION_3, R.string.wiimote_extension_6);
    titles.put(MenuTag.WIIMOTE_EXTENSION_4, R.string.wiimote_extension_7);
  }

  public static void launch(Context context, MenuTag menuTag, String gameId)
  {
    Intent settings = new Intent(context, SettingsActivity.class);
    settings.putExtra(ARG_MENU_TAG, menuTag);
    settings.putExtra(ARG_GAME_ID, gameId);
    context.startActivity(settings);
  }

  @Override
  protected void onCreate(Bundle savedInstanceState)
  {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_settings);

    Intent launcher = getIntent();
    String gameID = launcher.getStringExtra(ARG_GAME_ID);
    MenuTag menuTag = (MenuTag) launcher.getSerializableExtra(ARG_MENU_TAG);
    mPresenter.onCreate(savedInstanceState, menuTag, gameID);
  }

  @Override
  public boolean onCreateOptionsMenu(Menu menu)
  {
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.menu_settings, menu);

    return true;
  }

  @Override
  public boolean onOptionsItemSelected(MenuItem item)
  {
    return mPresenter.handleOptionsItem(item.getItemId());
  }

  @Override
  protected void onSaveInstanceState(Bundle outState)
  {
    // Critical: If super method is not called, rotations will be busted.
    super.onSaveInstanceState(outState);
    mPresenter.saveState(outState);
  }

  @Override
  protected void onStart()
  {
    super.onStart();
    mPresenter.onStart();
  }

  /**
   * If this is called, the user has left the settings screen (potentially through the
   * home button) and will expect their changes to be persisted. So we kick off an
   * IntentService which will do so on a background thread.
   */
  @Override
  protected void onStop()
  {
    super.onStop();

    mPresenter.onStop(isFinishing());
  }

  @Override
  public void onBackPressed()
  {
    mPresenter.onBackPressed();
  }

  @Override
  public void showSettingsFragment(MenuTag menuTag, Bundle extras, boolean addToStack,
          String gameID)
  {
    FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();

    if (addToStack)
    {
      if (areSystemAnimationsEnabled())
      {
        transaction.setCustomAnimations(
                R.animator.settings_enter,
                R.animator.settings_exit,
                R.animator.settings_pop_enter,
                R.animator.setttings_pop_exit);
      }

      transaction.addToBackStack(null);
      mPresenter.addToStack();
    }
    transaction.replace(R.id.frame_content, SettingsFragment.newInstance(menuTag, gameID, extras),
            FRAGMENT_TAG);

    transaction.commit();

    if (titles.containsKey(menuTag))
    {
      setTitle(titles.get(menuTag));
    }
  }

  private boolean areSystemAnimationsEnabled()
  {
    float duration = Settings.Global.getFloat(
            getContentResolver(),
            Settings.Global.ANIMATOR_DURATION_SCALE, 1);
    float transition = Settings.Global.getFloat(
            getContentResolver(),
            Settings.Global.TRANSITION_ANIMATION_SCALE, 1);
    return duration != 0 && transition != 0;
  }

  @Override
  public void startDirectoryInitializationService(DirectoryStateReceiver receiver,
          IntentFilter filter)
  {
    LocalBroadcastManager.getInstance(this).registerReceiver(
            receiver,
            filter);
    DirectoryInitialization.start(this);
  }

  @Override
  public void stopListeningToDirectoryInitializationService(DirectoryStateReceiver receiver)
  {
    LocalBroadcastManager.getInstance(this).unregisterReceiver(receiver);
  }

  @Override
  public void showLoading()
  {
    if (dialog == null)
    {
      dialog = new ProgressDialog(this);
      dialog.setMessage(getString(R.string.load_settings));
      dialog.setIndeterminate(true);
    }

    dialog.show();
  }

  @Override
  public void hideLoading()
  {
    dialog.dismiss();
  }

  @Override
  public void showPermissionNeededHint()
  {
    Toast.makeText(this, R.string.write_permission_needed, Toast.LENGTH_SHORT)
            .show();
  }

  @Override
  public void showExternalStorageNotMountedHint()
  {
    Toast.makeText(this, R.string.external_storage_not_mounted, Toast.LENGTH_SHORT)
            .show();
  }

  @Override
  public org.dolphinemu.dolphinemu.features.settings.model.Settings getSettings()
  {
    return mPresenter.getSettings();
  }

  @Override
  public void setSettings(org.dolphinemu.dolphinemu.features.settings.model.Settings settings)
  {
    mPresenter.setSettings(settings);
  }

  @Override
  public void onSettingsFileLoaded(
          org.dolphinemu.dolphinemu.features.settings.model.Settings settings)
  {
    SettingsFragmentView fragment = getFragment();

    if (fragment != null)
    {
      fragment.onSettingsFileLoaded(settings);
    }
  }

  @Override
  public void onSettingsFileNotFound()
  {
    SettingsFragmentView fragment = getFragment();

    if (fragment != null)
    {
      fragment.loadDefaultSettings();
    }
  }

  @Override
  public void showToastMessage(String message)
  {
    Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
  }

  @Override
  public void popBackStack()
  {
    getSupportFragmentManager().popBackStackImmediate();
  }

  @Override
  public void onSettingChanged()
  {
    mPresenter.onSettingChanged();
  }

  @Override
  public void onGcPadSettingChanged(MenuTag key, int value)
  {
    mPresenter.onGcPadSettingChanged(key, value);
  }

  @Override
  public void onWiimoteSettingChanged(MenuTag section, int value)
  {
    mPresenter.onWiimoteSettingChanged(section, value);
  }

  @Override
  public void onExtensionSettingChanged(MenuTag menuTag, int value)
  {
    mPresenter.onExtensionSettingChanged(menuTag, value);
  }

  private SettingsFragment getFragment()
  {
    return (SettingsFragment) getSupportFragmentManager().findFragmentByTag(FRAGMENT_TAG);
  }
}

SettingsActivityView.java:

package org.dolphinemu.dolphinemu.features.settings.ui;

import android.content.IntentFilter;
import android.os.Bundle;

import org.dolphinemu.dolphinemu.features.settings.model.Settings;
import org.dolphinemu.dolphinemu.utils.DirectoryStateReceiver;

/**
 * Abstraction for the Activity that manages SettingsFragments.
 */
public interface SettingsActivityView
{
  /**
   * Show a new SettingsFragment.
   *
   * @param menuTag    Identifier for the settings group that should be displayed.
   * @param addToStack Whether or not this fragment should replace a previous one.
   */
  void showSettingsFragment(MenuTag menuTag, Bundle extras, boolean addToStack, String gameId);

  /**
   * Called by a contained Fragment to get access to the Setting HashMap
   * loaded from disk, so that each Fragment doesn't need to perform its own
   * read operation.
   *
   * @return A possibly null HashMap of Settings.
   */
  Settings getSettings();

  /**
   * Used to provide the Activity with Settings HashMaps if a Fragment already
   * has one; for example, if a rotation occurs, the Fragment will not be killed,
   * but the Activity will, so the Activity needs to have its HashMaps resupplied.
   *
   * @param settings The ArrayList of all the Settings HashMaps.
   */
  void setSettings(Settings settings);

  /**
   * Called when an asynchronous load operation completes.
   *
   * @param settings The (possibly null) result of the ini load operation.
   */
  void onSettingsFileLoaded(Settings settings);

  /**
   * Called when an asynchronous load operation fails.
   */
  void onSettingsFileNotFound();

  /**
   * Display a popup text message on screen.
   *
   * @param message The contents of the onscreen message.
   */
  void showToastMessage(String message);

  /**
   * Show the previous fragment.
   */
  void popBackStack();

  /**
   * End the activity.
   */
  void finish();

  /**
   * Called by a containing Fragment to tell the Activity that a setting was changed;
   * unless this has been called, the Activity will not save to disk.
   */
  void onSettingChanged();

  /**
   * Called by a containing Fragment to tell the containing Activity that a GCPad's setting
   * was modified.
   *
   * @param menuTag Identifier for the GCPad that was modified.
   * @param value   New setting for the GCPad.
   */
  void onGcPadSettingChanged(MenuTag menuTag, int value);

  /**
   * Called by a containing Fragment to tell the containing Activity that a Wiimote's setting
   * was modified.
   *
   * @param menuTag Identifier for Wiimote that was modified.
   * @param value   New setting for the Wiimote.
   */
  void onWiimoteSettingChanged(MenuTag menuTag, int value);

  /**
   * Called by a containing Fragment to tell the containing Activity that an extension setting
   * was modified.
   *
   * @param menuTag Identifier for the extension that was modified.
   * @param value   New setting for the extension.
   */
  void onExtensionSettingChanged(MenuTag menuTag, int value);

  /**
   * Show loading dialog while loading the settings
   */
  void showLoading();

  /**
   * Hide the loading the dialog
   */
  void hideLoading();

  /**
   * Show a hint to the user that the app needs write to external storage access
   */
  void showPermissionNeededHint();

  /**
   * Show a hint to the user that the app needs the external storage to be mounted
   */
  void showExternalStorageNotMountedHint();

  /**
   * Start the DirectoryInitialization and listen for the result.
   *
   * @param receiver the broadcast receiver for the DirectoryInitialization
   * @param filter   the Intent broadcasts to be received.
   */
  void startDirectoryInitializationService(DirectoryStateReceiver receiver, IntentFilter filter);

  /**
   * Stop listening to the DirectoryInitialization.
   *
   * @param receiver The broadcast receiver to unregister.
   */
  void stopListeningToDirectoryInitializationService(DirectoryStateReceiver receiver);
}

1 个答案:

答案 0 :(得分:1)

鉴于您发布的内容,我认为最好的方法是

1)将此方法添加到您的SettingsActivityView界面中:

void setTitle(int titleId);

2)在您的SettingsActivityPresenter中,每当您想更改标题时,请致电

mView.setTitle(R.string.foo);