BaseActivity有一个布局和一个扩展了这个BaseActivity的子Activity。
如何绑定视图以便BaseActivity中的视图在BaseActivity中绑定,而Sub活动中的视图绑定在那里?
以下是解释当前场景的示例代码, 注意:示例代码取自here
基础活动
public class BaseActivity extends AppCompatActivity {
protected void onCreate(Bundle savedInstanceState, int layout) {
super.onCreate(savedInstanceState);
super.setContentView(layout);
ButterKnife.bind(this);
}
@Override
public void setContentView(int layoutResID) {
//I added my own implementation here
}
}
次级活动
public class SplashActivity extends BaseActivity {
@BindView(R.id.txtName)
TextView txtName;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ButterKnife.bind(this);
}
}
上述方案产生了许多错误,例如无法找到带有id的视图,
经过大量的研究,我发现很多话题都在讨论,
所以在浏览完所有链接后,我尝试了以下组合,但没有一个工作
ButterKnife.bind(this)
但不在SplashActivity
ButterKnife.bind(this)
。ButterKnife.bind(this)
中呼叫SplashActivity
,使用此组合我无法访问BaseActivity的视图项,因为它们原来是null。我的问题
如何绑定BaseActivity
和SplashActivity
查看项目?
确切错误行
Caused by: java.lang.IllegalStateException: Required view '' with ID 2131296567 for field '' was not found. If this view is optional add '@Nullable' (fields) or '@Optional' (methods) annotation.
对于您的善意说明,视图中存在视图。
修改1:
我添加了覆盖setContentView();
答案 0 :(得分:3)
简单。
将您的抽象BaseActivity视为:
public abstract class BaseActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(getLayoutResource());
ButterKnife.bind(this);
}
protected abstract int getLayoutResource();
}
然后只需使用BaseActivity
扩展您的活动:
public class SplashActivity extends BaseActivity {
@BindView(R.id. txtName)
TextView textView;
@Override
protected int getLayoutResource() {
return R.layout.activity_splash;
}
}
我更喜欢在我的项目中拥有多个Base类。您可以将BaseToolbarActivity
扩展为BaseActivity
:
public abstract class BaseToolBarActivity extends BaseActivity {
protected static final int RESOURCE_NO_MENU = 0;
@BindView(R.id.toolbar)
Toolbar mToolbar;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setToolBar();
}
public void setToolBar() {
setSupportActionBar(mToolbar);
}
protected abstract int getMenuResource();
@Override
public boolean onCreateOptionsMenu(Menu menu) {
if (getMenuResource() == RESOURCE_NO_MENU)
return super.onCreateOptionsMenu(menu);
else {
getMenuInflater().inflate(getMenuResource(), menu);
return true;
}
}
}
因此,如果您的Activity
具有布局工具栏,则将其扩展为BaseToolbarActivity
,否则将其扩展为BaseActivity
对于更多此类,您可以在
中引用我的项目答案 1 :(得分:2)
我只是意识到要查看其中一条评论。我认为你的真正问题根本不在于子类化。它是布局。 我认为你想要在超类布局中包含子类布局。不幸的是,你正在破坏子类中的超类布局。 我认为您需要在子类中包含基本活动布局(可能包含在布局中的合并标记中)..请参阅 Re-using Layouts with include - 在您的子类布局(启动画面)中包含您的基本活动布局(工具栏等)..
-
(我认为以下信息现在无关紧要,但如果您感兴趣,请将其保留在那里)
所以,如果我正确地理解了这个问题,那么在子类(splashactivity)可以设置其布局之前,似乎基本上超级类中的butterknife bindng(基本活动)正在发生。
使用getLayourResourceId(在子类中重写)的想法可能适用于大多数人,因为它是一种允许子活动在调用butterknife.bind之前将其布局指定为超级活动的方法。
因此,假设这是正确的,另一种解决问题的方法是延迟绑定,直到指定布局为止。
换句话说,;
public class BaseActivity extends AppCompatActivity {
// Removed layout parameter
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// It may not make sense to set the content view if it is always
// replaced by the subclasses, but maybe you want a default?
setContentView(R.layout.baseactivitylayout);
...稍后调用onStart时会调用bind .... }
...
public void onStart() {
super.onStart();
ButterKnife.bind(this);
}
...
}
和
public class SplashActivity extends BaseActivity {
@BindView(R.id.txtName)
TextView txtName;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.splashLayout);
// butterknife.bind will be called when BaseActivity's onStart is called.
}
}
当然,从onStart开始绑定并不总是方便(或正确),但它可能有助于阐明其他解决方案的工作原理。
祝你好运, CJ答案 2 :(得分:1)
异常中的消息告诉您该怎么做:
找不到字段“txtName”的ID为2131296567的必需视图“txtName”。如果此视图是可选的,请添加“@nullable”注释。
将其添加到布局中或使用@Nullable注释使字段绑定可选。
请参阅此Link
答案 3 :(得分:1)
在活动A中,您将设置活动的实例A.删除BaseActivity中的butterknife.bind。
super.setContentView(layout);
ButterKnife.bind(this);
使用ButterKnife.bind在childActivity中分配View实例。
super.onCreate(savedInstanceState);
ButterKnife.bind(this);
表示片段
ButterKnife.Bind(View,this);
你正在移除基础活动中的奶油刀。
原因在于: - 在基础活动中没有视图存在的重量分配不必要的假设有超过10个活动不容易管理。
答案 4 :(得分:1)
将您的BaseActivity
更新为:
public class BaseActivity extends AppCompatActivity {
protected void onCreate(Bundle savedInstanceState, int layout) {
super.onCreate(savedInstanceState);
setContentView(layout);
ButterKnife.bind(this);
}
}
并且SubActivity
为:
public class SplashActivity extends BaseActivity {
@BindView(R.id.txtName)
TextView txtName;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState, R.layout.activity_splash);
}
}