我有一个Activity A
,其中包含Fragment B
,其中包含另一个Fragment C
,其中包含ListView
,其中包含一些列表项。
列表项如何与Activity
进行通信?我必须逐级传递Activity
参考级别,直到它到达列表项目为止?我必须创建多个接口,并将通信级别提升回Activity
级别吗?
更新
在阅读 @Barend 的回答后,这是我的代码:Fragment C
有一个界面C
。 Fragment B
有一个B
接口,扩展了C
。 Activity A
实现B
,这意味着它还在C
中实现方法。在Fragment C
中,我有一个mListener
字段,该字段已分配给getActivity()
生命周期回调中的onAttach(Context)
。
答案 0 :(得分:1)
如果您需要与const
中的Activity
进行通信,则只需使用fragment
即可从任何嵌套Activity
获取Fragment
。
如果您需要getActivity()
Fragment
Activity
FragmentManager
FragmentManager manager = getFragmentManager();
Fragment f = manager.findFragmentByTag("Your fragment tag");
使用class Crypter
{
/**
*
* Encryption key
*
* @var
*/
protected $key;
/**
*
* Encryption vector
*
* @var
*/
protected $iv;
public function __construct()
{
$this->key = config('auth.triple_des_key');
$this->iv = implode(array_map("chr", config('auth.triple_des_iv')));
}
/**
*
* Decrypts string using tripleDES method.
*
* @param $input String
* @return String
*/
public function decryptTripleDES($input)
{
$td = mcrypt_module_open(MCRYPT_3DES, '', MCRYPT_MODE_CBC, '');
$encryptedData = base64_decode($input);
$key = iconv('utf-8', 'us-ascii//TRANSLIT', $this->key);
$key = md5($key, true);
$key .= substr($key, 0, 8);
mcrypt_generic_init($td, $key, $this->iv);
$decryptedData = mdecrypt_generic($td, $encryptedData);
mcrypt_generic_deinit($td);
//remove the padding text
$block = mcrypt_get_block_size("tripledes", "cbc");
$packing = ord($decryptedData{strlen($decryptedData) - 1});
if ($packing and ($packing < $block)) {
for ($P = strlen($decryptedData) - 1; $P >= strlen($decryptedData) - $packing; $P--) {
if (ord($decryptedData[$P]) != $packing) {
$packing = 0;
}
}
}
$decryptedData = substr($decryptedData, 0, strlen($decryptedData) - $packing);
return $decryptedData;
}
}
,请访问clone
:
addAll
答案 1 :(得分:1)
如果你想要最干净的面向对象的结构,你可以使用多个接口,给回调接口提供与片段相同的嵌套结构,如下所示:
public class InnerFragment extends Fragment {
public interface Callback {
// Defines all callback methods required by inner fragment
}
}
public class OuterFragment extends Fragment {
public interface Callback
extends InnerFragment.Callback {
// Defines all callback methods required by outer fragment
// Inherits all callback methods required by inner fragment
}
}
public class HostActivity extends Activity
implements OuterFragment.Callback {
// implements the callback methods of both fragments, but
// references only the outer fragment
}
您支付的价格是,这使您编写的代码比使用广播接收器或事件总线的代码多。
为什么这是最干净的方法?关注点分离和最少知识原则。活动仅与外部片段直接交互;内部片段是外部片段的实现细节。
要使内部片段起作用,活动必须实现内部回调。这是通过使外部回调扩展内部回调来实现的。
如果你勾勒出&#34;组件x了解组件y&#34;图表,你明白了:
Activity --> OuterFragment --> InnerFragment
这很干净。这些组件自包含和独立,其依赖关系显式和(大部分)编译器检查。 InnerFragment是一个黑盒子&#34;外部片段的实现细节,它可以直接在不同的上下文中使用,如果回调没有改变(它们可能从一个片段的回调移动到另一个片段),任何一个片段都可以重构而不触及活动在某些情况下)。
如果您不使用callback-extends-callback技巧,那么您将获得此组件知识图:
Activity --> OuterFragment --> InnerFragment
--------------------> InnerFragment
在这种情况下,内部片段回调依赖项对程序员是不可见的。如果您包含片段X,则您希望必须实现X.Callback,但是您还需要Y.Callback并不明显。由于这通常是通过Fragment onAttach()
方法中的类型转换来实现的,因此在运行时获得ClassCastException
之前,您不会发现。
顺便说一句,我不喜欢嵌套片段(DialogFragment
很好,但我对嵌套常规片段持怀疑态度)。我认为片段增加了很多复杂性,我还没有真正遇到过这样的情况,即移动应用的小屏幕尺寸和单个任务焦点需要甚至是可以理解的。您通常最好使用自定义ViewGroup
。我建议仅使用片段作为支持平板电脑上具有并排布局的手机上的堆叠布局的方式,甚至可以使用自定义ViewGroup
以一种通常更简单但可以肯定的方式实现不太常见。