2017-04-05 129 views
0

我創建了一個基本片段類,它處理設置工具欄標題,註冊片段連接時間,設置菜單圖標和其他一些內容。我的問題是,我決定使用PreferencesFragmentCompat來設置我的設置片段,我不能擴展我的BaseFragment和androids PreferencesFragmentCompat。在這裏使用接口不會有幫助,因爲我的BaseFragment具有很多功能,而且我不想將它複製到每個片段類中。通常擴展兩個類,你只需要在兩個獨立的文件中做,但因爲兩者已經擴展了Androids Fragment類,我不知道這是如何可能的。有沒有更好的方法來做到這一點?具有多種不同片段類型的Android BaseFragment類

enter image description here

BaseFragment:

public abstract class BaseFragment extends Fragment { 

    protected View rootView; 
    protected AppSettings settings; 
    protected LayoutInflater inflater; 

    public static void startFragment(Activity activity, BaseFragment newFragment) { 
     FragmentManager fragManager = ((AppCompatActivity) activity).getSupportFragmentManager(); 
     BaseFragment currentFragment = (BaseFragment) fragManager.findFragmentById(R.id.fragment_container); 

     // Start the transactions 
     FragmentTransaction transaction = fragManager.beginTransaction(); 
     transaction.replace(R.id.fragment_container, newFragment); 

     // If there is already a fragment then we want it on the backstack 
     if (currentFragment != null) { 
      transaction.addToBackStack(null); 
     } 

     // Show it 
     transaction.commit(); 
    } 

    @TargetApi(21) 
    private void lockMode(boolean start) { 
     if (android.os.Build.VERSION.SDK_INT >= 16) { 
      if (start) { 
       getActivity().startLockTask(); 
      } else { 
       getActivity().stopLockTask(); 
      } 
     } 
    } 

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

     // Get a reference to the app settings 
     settings = AppSettings.getInstance(getActivity()); 

     // Don't want keyboard to stay open between fragments 
     hideKeyboard(); 

     ActionBar actionBar = ((AppCompatActivity) getActivity()).getSupportActionBar(); 
     if (actionBar != null) { 
      if (toolbarElevation()) { 
       actionBar.setElevation(4 * getActivity().getResources().getDisplayMetrics().density); 
      } else { 
       actionBar.setElevation(0); 
      } 
     } 

     setHasOptionsMenu(true); 
    } 

    @Override 
    public void onResume() { 
     super.onResume(); 

     // Set the title up 
     Toolbar toolbar = (Toolbar) getActivity().findViewById(R.id.toolbar); 
     toolbar.setTitle(getTitle()); 

     // Enable the home button in the action bar 
     ((AppCompatActivity) getActivity()).getSupportActionBar().setDisplayShowHomeEnabled(true); 

     // Change the home button icon for menu or back 
     if (showUpNavigation()) { 
      toolbar.setNavigationIcon(R.drawable.ic_navigation_back_white); 
     } else { 
      toolbar.setNavigationIcon(R.drawable.ic_menu_white); 
     } 

     if (isAppInLockTaskMode() == true && pinnedMode() == false) { 
      lockMode(false); 
     } 

     setDrawerMenu(); 
    } 

    public boolean getAuthRequired() { 
     return true; 
    } 

    public boolean isBackAllowed() { 
     return true; 
    } 

    public boolean toolbarElevation() { 
     return true; 
    } 

    public String getTitle() { 
     return "ISOPED"; 
    } 

    public boolean pinnedMode() { 
     return false; 
    } 

    public boolean showUpNavigation() { 
     return false; 
    } 

    public void hideKeyboard() { 
     InputMethodManager inputManager = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE); 

     // check if no view has focus: 
     View v = getActivity().getCurrentFocus(); 
     if (v == null) { 
      return; 
     } 

     inputManager.hideSoftInputFromWindow(v.getWindowToken(), 0); 
    } 

    public void setDrawerMenu() { 
     NavigationView navigationView = (NavigationView) getActivity().findViewById(R.id.drawer_navigation); 
     Integer menuID = null; 
     Integer currentMenuId = null; 

     if (settings.isType(AppSettings.TYPES.PERSONAL)) { 
      menuID = R.menu.drawer_personal; 
     } else if (settings.isType(AppSettings.TYPES.PROFESSIONAL)) { 
      if (getAuthRequired() == true) { 
       menuID = R.menu.drawer_professional_locked; 
      } else { 
       menuID = R.menu.drawer_professional_unlocked; 
      } 
     } 

     if (menuID != null) { 
      if (navigationView.getTag() != null) { 
       currentMenuId = (Integer) navigationView.getTag(); 
      } 

      if (currentMenuId == null || navigationView.getMenu().size() == 0 || currentMenuId != menuID) { 
       navigationView.getMenu().clear(); 
       navigationView.inflateMenu(menuID); 
       navigationView.setTag(Integer.valueOf(menuID)); 
      } 
     } 
    } 

    @Override 
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { 
     super.onCreateOptionsMenu(menu, inflater); 
     menu.clear(); 

     if (settings.isType(AppSettings.TYPES.PROFESSIONAL) && pinnedMode() && false == isAppInLockTaskMode()) { 
      inflater.inflate(R.menu.pin_menu, menu); 
     } 
    } 

    @Override 
    public boolean onOptionsItemSelected(MenuItem item) { 
     DrawerLayout drawer = (DrawerLayout) getActivity().findViewById(R.id.drawer_layout); 

     switch (item.getItemId()) { 
      case android.R.id.home: 
       if (showUpNavigation()) { 
        getActivity().onBackPressed(); 
       } else { 
        drawer.openDrawer(GravityCompat.START); 
       } 
       return true; 
      case R.id.menu_pin: 
       if (isAppInLockTaskMode()) { 
        PinDialog dialog = new PinDialog((AppCompatActivity) getActivity(), new NavigationCallback((AppCompatActivity) getActivity()) { 
         @Override 
         public void run() { 
          lockMode(false); 
         } 
        }); 
        dialog.show(); 
       } else { 
        lockMode(true); 
       } 
       return true; 
     } 
     return super.onOptionsItemSelected(item); 
    } 

    private boolean isAppInLockTaskMode() { 
     ActivityManager activityManager; 

     activityManager = (ActivityManager) 
       getActivity().getSystemService(Context.ACTIVITY_SERVICE); 

     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { 
      // For SDK version 23 and above. 
      return activityManager.getLockTaskModeState() 
        != ActivityManager.LOCK_TASK_MODE_NONE; 
     } 

     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 
      // When SDK version >= 21. This API is deprecated in 23. 
      return activityManager.isInLockTaskMode(); 
     } 

     return false; 
    } 
} 

回答

1

這是一個很好的例子,在那裏你應該申請Joshua Bloch"Favor composition over inheritance"成語。

您可以委派所有已應用到BaseFragment一些類FragmentHelper邏輯:

public class FragmentHelper { 

    private final Fragment fragment; 

    public FragmentHelper(Fragment fragment) { 
     this.fragment = fragment; 
    } 

    public void create(Bundle bundle) { 
     // `BaseFragment`'s code goes here 
    } 

    public void resume() { 
     // `BaseFragment`'s code goes here 
    } 

    ... 
} 

現在,在您BaseFragment:

public class BaseFragment { 

    private FragmentHelper fragmentHelper; 

    @Override 
    public void onCreate(@Nullable Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     ... 
     fragmentHelper = new FragmentHelper(this); 
     fragmentHelper.create(savedInstanceState); 
    } 

    @Override 
    public void onResume() { 
     fragmentHelper.resume(); 
    } 
} 

而同樣這應該適用於類這是延伸PreferenceFragment

因此,你會逃避代碼重複。

參考:

  • 約書亞布洛赫 - 有效的Java第二版,第16項。