如何在 Fragments 中实现 onBackPressed()?
Posted
技术标签:
【中文标题】如何在 Fragments 中实现 onBackPressed()?【英文标题】:How to implement onBackPressed() in Fragments? 【发布时间】:2011-07-23 20:22:18 【问题描述】:有没有一种方法可以在 android Fragment 中实现onBackPressed()
,类似于我们在 Android Activity 中的实现方式?
由于片段生命周期没有onBackPressed()
。有没有其他替代方法可以在 Android 3.0 片段中覆盖onBackPressed()
?
【问题讨论】:
恕我直言,片段不应该知道也不应该关心返回按钮。一个 Activity 可以关心 BACK 按钮,尽管片段通常由 FragmentManager 处理。但是由于片段不知道其更大的环境(例如,它是否是活动中的几个之一),因此片段尝试确定正确的 BACK 功能是不是真的很安全。 当所有的fragment都显示一个WebView,你希望WebView在按下返回按钮时“返回”到上一页怎么样? Michael Herbig 的回答对我来说是完美的。但是对于那些不能使用 getSupportFragmentManager() 的人。请改用 getFragmentManager()。 回答 mharper 可能是你可以做类似 webview.setOnKeyListener(new OnKeyListener() @Override public boolean onKey(View v, int keyCode, KeyEvent event) if (keyCode == KeyEvent. KEYCODE_BACK && webview.canGoBack()) webview.goBack(); return true; return false; ); 嗨,有一种更好、更简洁的方法。官方文档也有记载:developer.android.com/guide/navigation/navigation-custom-back 【参考方案1】:不要实现 ft.addToBackStack() 方法,这样当你按下返回按钮时你的活动就会结束。
proAddAccount = new ProfileAddAccount();
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.fragment_container, proAddAccount);
//fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
【讨论】:
告诉我***.com/questions/32132623/… 最好覆盖 onBackPressed 函数如下: @Override public void onBackPressed() if (getSupportFragmentManager().getBackStackEntryCount() == 0) finish(); else FragmentManager fm = getSupportFragmentManager(); fm.popBackStack();如果没有片段 popBackStack 完成活动,否则 popBack 那里有什么。【参考方案2】:在 Activity 生命周期中,当我们使用 FragmentActivity 或 AppCompatActivity 时,android 后退按钮总是处理 FragmentManager 事务。 要处理 backstack,我们不需要处理它的 backstack 计数或标记任何内容,但我们应该保留添加或替换片段时的焦点。后退键情况请找以下sn-ps处理,
public void replaceFragment(Fragment fragment)
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
if (!(fragment instanceof HomeFragment))
transaction.addToBackStack(null);
transaction.replace(R.id.activity_menu_fragment_container, fragment).commit();
在这里,我不会为我的主页片段添加回栈,因为它是我的应用程序的主页。如果将 addToBackStack 添加到 HomeFragment 则应用程序将等待删除活动中的所有框架然后我们将得到空白屏幕所以我保持以下条件,
if (!(fragment instanceof HomeFragment))
transaction.addToBackStack(null);
现在,您可以在活动中看到之前添加的片段,并且应用程序将在到达 HomeFragment 时退出。你也可以看看下面的sn-ps。
@Override
public void onBackPressed()
if (mDrawerLayout.isDrawerOpen(Gravity.LEFT))
closeDrawer();
else
super.onBackPressed();
【讨论】:
【参考方案3】:片段: 制作一个 BaseFragment 放置一个方法:
public boolean onBackPressed();
活动:
@Override
public void onBackPressed()
List<Fragment> fragments = getSupportFragmentManager().getFragments();
if (fragments != null)
for (Fragment fragment : fragments)
if (!fragment.isVisible()) continue;
if (fragment instanceof BaseFragment && ((BaseFragment) fragment).onBackPressed())
return;
super.onBackPressed();
您的活动将在附加的可见片段上运行,并在每个片段上调用 onBackPressed() 并在其中一个返回“true”时中止(意味着它已被处理,所以没有进一步的行动)。
【讨论】:
先生,这是最优雅的方式,而且效果很好!【参考方案4】:您可以在活动中注册片段以处理后按:
interface BackPressRegistrar
fun registerHandler(handler: BackPressHandler)
fun unregisterHandler(handler: BackPressHandler)
interface BackPressHandler
fun onBackPressed(): Boolean
用法:
在片段中:
private val backPressHandler = object : BackPressHandler
override fun onBackPressed(): Boolean
showClosingWarning()
return false
override fun onResume()
super.onResume()
(activity as? BackPressRegistrar)?.registerHandler(backPressHandler)
override fun onStop()
(activity as? BackPressRegistrar)?.unregisterHandler(backPressHandler)
super.onStop()
活动中:
class MainActivity : AppCompatActivity(), BackPressRegistrar
private var registeredHandler: BackPressHandler? = null
override fun registerHandler(handler: BackPressHandler) registeredHandler = handler
override fun unregisterHandler(handler: BackPressHandler) registeredHandler = null
override fun onBackPressed()
if (registeredHandler?.onBackPressed() != false) super.onBackPressed()
【讨论】:
【参考方案5】:在 kotlin 中,它更简单。
override fun onViewCreated(view: View, savedInstanceState: Bundle?)
requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner, object : OnBackPressedCallback(true)
override fun handleOnBackPressed()
//
)
【讨论】:
这是 kotlin 开发人员的最佳解决方案之一。谢谢大佬。【参考方案6】:最佳解决方案,
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v7.app.AppCompatActivity;
public class BaseActivity extends AppCompatActivity
@Override
public void onBackPressed()
FragmentManager fm = getSupportFragmentManager();
for (Fragment frag : fm.getFragments())
if (frag == null)
super.onBackPressed();
finish();
return;
if (frag.isVisible())
FragmentManager childFm = frag.getChildFragmentManager();
if (childFm.getFragments() == null)
super.onBackPressed();
finish();
return;
if (childFm.getBackStackEntryCount() > 0)
childFm.popBackStack();
return;
else
fm.popBackStack();
if (fm.getFragments().size() <= 1)
finish();
return;
【讨论】:
【参考方案7】:从您的片段中,只需使用
requireActivity().onBackPressed();
处理点击添加 binding.actionABack.setOnClickListener(v -> requireActivity().onBackPressed());
【讨论】:
【参考方案8】:如果你有一个活动 A 并且你制作了 3 个片段,比如 B 、C 和 D ,这很简单。现在如果你在片段 B 或 C 中并且onBackPressed
你想每次都在片段 D 上移动。那么你有只需覆盖主 Activity A 中的 onBackPressed()
方法,并且当您跳转到任何片段时,然后传递您在主 Activity A 中识别该片段的那个片段的 TAG 或名称。
我举一个例子,你可以很容易地理解......
if (savedInstanceState == null)
getSupportFragmentManager().beginTransaction().add(R.id.container, new C_fragment(),"xyz").commit();
或者,如果您从片段 B 移动到片段 C..并且在后按时您想进入片段 D...如下所示
btn.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View view)
getActivity().getSupportFragmentManager().beginTransaction().add(R.id.container, new C_frament(), "xyz").commit();
((ActionBarActivity) getActivity()).getSupportActionBar().setTitle("Fragment C");
);
现在你必须在主要活动中重写 onBackPressed() 方法..如下所示..
@Override
public void onBackPressed()
FragmentManager fragmentManager =getSupportFragmentManager();
if (((C_fragment) getSupportFragmentManager().findFragmentByTag("xyz")) != null && ((C_fragment) getSupportFragmentManager().findFragmentByTag("xyz")).isVisible())
Fragment fragment = new D_Fragment();
fragmentManager.beginTransaction().replace(R.id.container, fragment).commit();
getSupportActionBar().setTitle("D fragment ");
else
super.onBackPressed();
【讨论】:
【参考方案9】:我使用了另一种方法如下:
Otto event bus 用于在 Activity 及其 Fragments 之间进行通信 Activity 中的堆栈包含自定义 back 操作,该操作包装在调用片段定义的Runnable
中
当在控制 Activity 中调用 onBackPressed
时,它会弹出最近的自定义 back 操作并执行其 Runnable
。如果堆栈上没有任何内容,则调用默认的super.onBackPressed()
带有示例代码的完整方法包含在here 作为this other SO question 的答案。
【讨论】:
【参考方案10】:我知道为时已晚,但上周我遇到了同样的问题。没有一个答案对我有帮助。然后我在玩代码,这很有效,因为我已经添加了片段。
在您的活动中,为ViewPager
设置OnPageChangeListener
,以便您知道用户何时处于第二个活动中。如果他在第二个活动中,请按如下方式制作布尔值true
:
mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
// Set up the ViewPager with the sections adapter.
mViewPager = (ViewPager) findViewById(R.id.pager);
mViewPager.setAdapter(mSectionsPagerAdapter);
mViewPager.setCurrentItem(0);
mViewPager.addOnPageChangeListener(new OnPageChangeListener()
@Override
public void onPageSelected(int position)
// TODO Auto-generated method stub
mSectionsPagerAdapter.instantiateItem(mViewPager, position);
if(position == 1)
inAnalytics = true;
else if(position == 0)
inAnalytics = false;
@Override
public void onPageScrolled(int position, float arg1, int arg2)
// TODO Auto-generated method stub
@Override
public void onPageScrollStateChanged(int arg0)
// TODO Auto-generated method stub
);
现在在按下后退按钮时检查布尔值并将当前项目设置为您的第一个片段:
@Override
public void onBackPressed()
if(inAnalytics)
mViewPager.setCurrentItem(0, true);
else
super.onBackPressed();
【讨论】:
【参考方案11】:好吧,伙计们,我终于找到了一个好的解决方案。
在包含片段的活动中的 onCreate() 中,添加一个 backstack 更改侦听器,如下所示:
fragmentManager.addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener()
@Override
public void onBackStackChanged()
List<Fragment> f = fragmentManager.getFragments();
//List<Fragment> f only returns one value
Fragment frag = f.get(0);
currentFragment = frag.getClass().getSimpleName();
);
(另外添加我的 fragmenManager 在活动 O 中声明 现在每次更改片段时,当前片段字符串将成为当前片段的名称。然后在 onBackPressed() 活动中,您可以控制后退按钮的操作,如下所示:
@Override
public void onBackPressed()
switch (currentFragment)
case "FragmentOne":
// your code here
return;
case "FragmentTwo":
// your code here
return;
default:
fragmentManager.popBackStack();
// default action for any other fragment (return to previous)
我可以确认此方法对我有效。
【讨论】:
【参考方案12】:只需在 onKeyUp() 中执行:
@Override
public boolean onKeyUp(int keyCode, KeyEvent event)
if (keyCode == KeyEvent.KEYCODE_BACK)
// do something
return true; // return true if back handled, false otherwise
return super.onKeyUp(keyCode, event);
【讨论】:
片段没有onKeyUp
:developer.android.com/reference/kotlin/androidx/fragment/app/…【参考方案13】:
如果你真的想在 Fragment 中启用 onBackPressed(),试试这个。 在浪费了一个小时的时间之后,根据我以前的经验,我制作了这个完全符合需求的解决方案。
您只需要关注private int STATUS_FRAGMENT=0;
的值即可满足片段中addToBackStack()
的需要。
import android.view.MenuItem;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import com.example.growfast.NavigationItemsFolder.CoreFragments.Cart;
import com.example.growfast.NavigationItemsFolder.CoreFragments.HelpDesk;
import com.example.growfast.NavigationItemsFolder.CoreFragments.Home;
import com.example.growfast.NavigationItemsFolder.CoreFragments.ProfileDetails;
import com.example.growfast.R;
import com.google.android.material.bottomnavigation.BottomNavigationView;
public class BusinessManagement extends AppCompatActivity
public BottomNavigationView bottomNavigationView;
private int STATUS_FRAGMENT=0;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_base_layout);
setBottomNavigationMenu();
private void setBottomNavigationMenu()
bottomNavigationView = findViewById(R.id.navigation);
bottomNavigationView.setVisibility(View.VISIBLE);
bottomNavigationView.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener()
Fragment fragment = null;
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item)
switch (item.getItemId())
case R.id.action_home:
fragment = new Home();
break;
case R.id.action_profile:
fragment = new ProfileDetails();
break;
case R.id.action_cart:
fragment = new Cart();
break;
case R.id.action_favourites_menu:
fragment = new HelpDesk();
break;
return loadFromFragment(fragment);
);
bottomNavigationView.setSelectedItemId(R.id.action_home);
private boolean loadFromFragment(Fragment fragment)
if (fragment != null)
getSupportFragmentManager().beginTransaction().replace(R.id.my_container, fragment)
.commit();
STATUS_FRAGMENT=1;
return true;
return false;
@Override
public void onBackPressed()
if (STATUS_FRAGMENT==1)
bottomNavigationView.setSelectedItemId(R.id.action_home);
STATUS_FRAGMENT=0;
bottomNavigationView.setVisibility(View.VISIBLE);
else
super.onBackPressed();
```
【讨论】:
【参考方案14】:这是我处理按下后退按钮上的片段的答案。 当单击将片段附加到活动的项目时,我有五个项目(A、B、C、D、E)的底部导航以附加到活动。 假设点击项目(A)我附加片段(A)然后如果点击项目(B)然后我附加片段(B)等等。
点击项的流程。 A->B->C->D->E
按下后退按钮的流程。 E->D->C->B->A
@Override
public void onBackPressed()
int count = getSupportFragmentManager().getBackStackEntryCount();
if (count == 0)
super.onBackPressed();
else
int index = ((getSupportFragmentManager().getBackStackEntryCount()) -1);
getSupportFragmentManager().popBackStack();
FragmentManager.BackStackEntry backEntry = getSupportFragmentManager().getBackStackEntryAt(index);
int stackId = backEntry.getId();
bottomNavigationView.getMenu().getItem(stackId).setChecked(true);
【讨论】:
【参考方案15】:如果你需要在 Fragment 中实现,你应该use an interface。
另一方面,如果您需要在活动中实现,例如。执行一个简单的finish()
Activity 执行以下操作:
YourActivity.kt
override fun onBackPressed()
Log.d(this.javaClass.simpleName, "onBackPressed() called")
if (supportFragmentManager.fragments.any it is YourFragment )
finish()
return
【讨论】:
【参考方案16】:在你的 mainActivity 实现回调接口
protected mainActivity.OnBackPressedListener onBackPressedListener;
public interface OnBackPressedListener
void doBack();
public void setOnBackPressedListener(mainActivity.OnBackPressedListener onBackPressedListener)
this.onBackPressedListener = onBackPressedListener;
@Override
public void onBackPressed()
if (onBackPressedListener != null)
onBackPressedListener.doBack();
else
super.onBackPressed();
在片段上实现我们在 mainActivity 中编写的接口 OnBackPressedListener 就像
implements mainActivity.OnBackPressedListener
mainActivity 是我的基本活动,在您的片段 onCreateView 方法中编写以下代码
((mainActivity) getActivity()).setOnBackPressedListener(this);
并实现OnBackPressedListener接口方法doBack
@Override
public void doBack()
//call base fragment
现在使用 doBack() 方法调用您要在后按时调用的片段
【讨论】:
【参考方案17】:private boolean isMainFragment = true;
@Override
public void onBackPressed()
if (isMainFragment)
finish();
else
getSupportFragmentManager().popBackStack();
isMainFragment = true;
当打开花药片段时,只需添加
isMainFragment = false;
跟我一起工作
【讨论】:
【参考方案18】:没有人提及我如何在这个逻辑中调用activity?.onBackPressed
。
所以我创建了一个可能对你有用的扩展:
fun Fragment.onBackClick(callback: (onBackPressedCallback: OnBackPressedCallback) -> Unit)
// This callback will only be called when MyFragment is at least Started.
activity?.onBackPressedDispatcher?.addCallback(viewLifecycleOwner)
callback.invoke(this)
当你的逻辑完成后,现在是激动人心的部分调用onBackPressed
:
片段中的示例使用:
onBackClick
if (shouldBackFromFrag)
//do your logic when pressed back
else
it.isEnabled = false //the key to disable the dispatcher
activity?.onBackPressed()
【讨论】:
【参考方案19】:我遇到了同样的问题,我为它创建了一个新的侦听器并在我的片段中使用。
1 - 你的活动应该有一个监听器接口和一个监听器列表
2 - 您应该实现添加和删除侦听器的方法
3 - 您应该重写 onBackPressed 方法以检查是否有任何侦听器使用后按
public class MainActivity ...
/**
* Back press listener list. Used for notifying fragments when onBackPressed called
*/
private Stack<BackPressListener> backPressListeners = new Stack<BackPressListener>();
...
/**
* Adding new listener to back press listener stack
* @param backPressListener
*/
public void addBackPressListener(BackPressListener backPressListener)
backPressListeners.add(backPressListener);
/**
* Removing the listener from back press listener stack
* @param backPressListener
*/
public void removeBackPressListener(BackPressListener backPressListener)
backPressListeners.remove(backPressListener);
// Overriding onBackPressed to check that is there any listener using this back press
@Override
public void onBackPressed()
// checks if is there any back press listeners use this press
for(BackPressListener backPressListener : backPressListeners)
if(backPressListener.onBackPressed()) return;
// if not returns in the loop, calls super onBackPressed
super.onBackPressed();
4 - 您的片段必须实现后按接口
5 - 您需要将片段添加为后按的侦听器
6 - 如果片段使用此后按,您应该从 onBackPressed 返回 true
7 - 重要 - 您必须从 onDestroy 列表中删除片段
public class MyFragment extends Fragment implements MainActivity.BackPressListener
...
@Override
public void onAttach(Activity activity)
super.onCreate(savedInstanceState);
// adding the fragment to listener list
((MainActivity) activity).addBackPressListener(this);
...
@Override
public void onDestroy()
super.onDestroy();
// removing the fragment from the listener list
((MainActivity) getActivity()).removeBackPressListener(this);
...
@Override
public boolean onBackPressed()
// you should check that if this fragment is the currently used fragment or not
// if this fragment is not used at the moment you should return false
if(!isThisFragmentVisibleAtTheMoment) return false;
if (isThisFragmentUsingBackPress)
// do what you need to do
return true;
return false;
使用 Stack 代替 ArrayList 可以从最新的片段开始。将片段添加到后台堆栈时也可能存在问题。因此,您需要在使用后按时检查片段是否可见。否则其中一个片段将使用该事件,并且最新片段不会在后按时关闭。
我希望这能解决每个人的问题。
【讨论】:
【参考方案20】:我只是使用findFragmentById
并转换为片段并调用处理onBackpressed 的方法。此示例显示检查这是否是订单流程中的第一步,如果弹出对话框片段以确认退出订单。
@Override
public void onBackPressed()
//check if first fragment in wizard is loaded, if true get abandon confirmation before going back
OrderFragment frag =(OrderFragment)getSupportFragmentManager().findFragmentById(R.id.fragContainer);
if (frag==null || (frag!=null && frag.getOrderStage()<1))
AlertDialogFragment.show(getSupportFragmentManager(), R.string.dialog_cancel_order,R.string.dialog_cancel_order_msg, R.string.dialog_cancel_order_pos,R.string.dialog_order_quiz_neg, DIALOG_ID_CANCEL);
else
super.onBackPressed();
【讨论】:
【参考方案21】:在 Fragments 中处理 onBackPressed() 的简单方法
第 1 步: 在活动中创建一个静态布尔值。
public static Fragment_one;
第 2 步: 在 On Create 方法中的 MainActivity(持有片段的活动)上,声明
Fragment_one=true;
第 3 步:在 MainActivity 中覆盖 onBackPressed()
@Override
public void onBackPressed()
if(Fragment_one)
//Back key pressed on fragment one
else
//Back key pressed on fragment two
第 4 步:在 fragment_one onCreateView 方法上声明
MainActivity.Fragment_one=true;
第五步关于fragment_two的onCreateView方法声明
MainActivity.Fragment_one=false;
注意:此方法仅适用于两个片段。
【讨论】:
【参考方案22】:这样实现 Fragment_1 -> Fragment_2 -> Fragment_3
Button btn = (Button) rootView.findViewById(R.id.your_button_id);
btn.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View view)
Fragment_2 nextFrag= new Fragment_2();
getActivity().getSupportFragmentManager().beginTransaction()
.replace(R.id.content_frame, nextFrag,getTag())
.addToBackStack(null)
.commit();
);
Fragment_3 -> Fragment_2 -> Fragment_1
Step_1:在 Base Activity 中创建可公开访问的字符串
Step_2:每当一个新的Fragment被激活时,改变Base Activity中String的值
Step_3:然后添加onBackPressed()方法并将String值传递给另一个可以替换fagments的方法
在基础活动中
public static String currentFragment=null;
@Override
public void onBackPressed()
displayPreviousFragment(currentFragment);
public void displayPreviousFragment(String currentFragment)
//creating fragment object
Fragment fragment = null;
//initializing the fragment object which is selected
switch (currentFragment)
case "Fragment_2" : fragment = new Fargment_1(); break;
case "Fragment_3" : fragment = new Fragment_2(); break;
//replacing the fragment
if (fragment != null)
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.frame_to_replace_fragment, fragment);
ft.commit();
在 Fragment_2 中 OnCreateView 方法内部
BaseActivity.currentFragment="Fragment_2";
在 Fragment_3 中 OnCreateView 方法内部
BaseActivity.currentFragment="Fragment_3";
【讨论】:
【参考方案23】:这行代码可以在任何片段中执行此操作,它将当前片段弹出到回栈中。
getActivity().getSupportFragmentManager().popBackStack();
【讨论】:
它弹出一个片段,但没有定义一个后按事件。 好吧,你总是可以覆盖容器活动的 onBackPress 回调,并将调用添加到 super.onBackPress。它将当前片段从堆栈中弹出,并将队列中的下一个片段带回前台。【参考方案24】:public interface IonBackPressInFrag
void backPressed();
public class FragmentMainActivity extends AppCompatActivity
public IonBackPressInFrag backPressInFrag;
@Override
protected void onCreate(Bundle savedInstanceState)
@Override
public void onBackPressed ()
backPressInFrag.backPressed();
public class FragDetailSearch extends Fragment implements IonBackPressInFrag
if(getActivity() !=null)
((FragmentMainActivity) getActivity()).backPressInFrag = this;
@Override
public void backPressed()
Toast.makeText(getContext(), "backkkkkk", Toast.LENGTH_LONG).show();
【讨论】:
【参考方案25】: @Override
public boolean onKeyDown(int keyCode, KeyEvent event)
if ((keyCode == KeyEvent.KEYCODE_BACK))
finish();
return super.onKeyDown(keyCode, event);
现在只需评论任何与 Key down 相关的方法 addToBackStack 将起作用。 谢谢
【讨论】:
【参考方案26】:这是我对该问题的解决方案:
在活动 A 中:
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == REQUEST_CODE)
if(resultCode == Activity.RESULT_OK)
tvTitle.setText(data.getExtras().getString("title", ""));
在活动 B 中:
@Override
public void onBackPressed()
setResult(Activity.RESULT_OK, getIntent());
super.onBackPressed();
活动 b 持有片段。
在片段中:
private void setText(String text)
Intent intent = new Intent();
intent.putExtra("title", text);
getActivity().setIntent(intent);
这样,活动 A 中的 Intent 对象“数据”将从片段中获取字符串
【讨论】:
以上是关于如何在 Fragments 中实现 onBackPressed()?的主要内容,如果未能解决你的问题,请参考以下文章
在Fragments中保存和恢复ListView(livedata)
如何在Castle.Core中实现IProxyGenerationHook的类中实现Equals和GetHashCode的覆盖方法?