我已经在我的Android应用程序中创建了自己的自定义适配器类,我从我的一个活动中调用它。我正在从适配器类添加一些元素到视图,我需要从我的活动类访问这些变量。
现在,理想情况下我希望它填充视图然后在我的activity类中执行更多代码,但是适配器类需要一些时间来填充视图,同时我的activity类中的其他代码正在执行尚未添加此类元素。 我该如何处理这种情况?我来自js背景。我们在java中有类似promises的内容吗?
根据答案,我将我的代码更改为:
public class HomeActivity extends Activity {
GridView grid;
String text[] = {"Calendar","Uber","Weather","News","Youtube","Clock","Email","Maps","Twitter","Facebook"};
String list_app_name[] = {"calendar","uber","weather","news","youtube","clock","email","maps","twitter","facebook"};
String id_button[] = {"button_calendar","button_uber","button_weather","button_news","button_youtube","button_clock","button_email","button_maps","button_twitter","button_facebook"};
int image[] = {R.drawable.social_icons1,R.drawable.social_icons2,R.drawable.social_icons3,R.drawable.social_icons4,
R.drawable.social_icons5,R.drawable.social_icons6, R.drawable.social_icons7,R.drawable.social_icons8,
R.drawable.social_icons9,R.drawable.social_icons10};
private DrawerLayout mDrawerLayout;
private ActionBarDrawerToggle mDrawerToggle;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_home);
//setting up the adapter for gridView
grid = (GridView)findViewById(R.id.simpleGrid);
ImageAdapter ia = new ImageAdapter(this,image,text,id_button);
grid.setAdapter(ia);
ia.notifyDataSetChanged();
try {
initStateOfApps();
} catch (JSONException e) {
e.printStackTrace();
}
}
public void initStateOfApps() throws JSONException {
Log.d("here","here");
ArrayList<String> list = getEnabledApps();
Log.d("apps",list.toString());
for(int i=0;i<list.size();i++) {
String app_name = list.get(i);
ToggleButton button=null;
if(app_name.equals("calendar")) {
button = (ToggleButton)findViewById(R.id.button_calendar);
button.setChecked(true);
}
}
}
}
所以发生的事情是我正在创建一些切换按钮,这些按钮会在我编写的ImageAdapter类中填充。
调用ImageAdapter后,我调用适配器上的notifydatasetchanged()
以更新视图。
我在适配器中做的是给每个切换按钮一些我在res/values/ids.xml
中写的自定义ID。
在每个切换按钮上使用setId
后,我尝试在我的activity class
中使用该ID,但它在我nullPointerException
中的initStateOfApps()
我试图改变状态按钮。
因此,即使使用notifyDataSetChanged
后,它仍然表现相同。
ImageAdapter.java
public class ImageAdapter extends BaseAdapter {
private Context context;
private final int item_image[];
private final String item_text[];
private final String button_id[];
public ImageAdapter(Context context, int item_image[], String[] item_text,String[] button) {
this.context = context;
this.item_image = item_image;
this.item_text = item_text;
this.button_id = button;
}
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View gridView;
if (convertView == null) {
gridView = new View(context);
// get layout from custom_gridview.xml
gridView = inflater.inflate(R.layout.item, null);
// set value into imageview
final ImageView image = (ImageView) gridView.findViewById(R.id.item_image);
image.setImageResource(item_image[position]);
// set value into textview
TextView text = (TextView) gridView.findViewById(R.id.item_text);
text.setText(item_text[position]);
final ToggleButton button_ = (ToggleButton) gridView.findViewById(R.id.item_button);
if(position==0) {
button_.setId(R.id.button_calendar);
image.setId(R.id.image_calendar);
}
button_.setOnCheckedChangeListener( new CompoundButton.OnCheckedChangeListener()
{
@Override
public void onCheckedChanged(CompoundButton toggleButton, boolean isChecked)
{
if(context.getResources().getResourceEntryName(toggleButton.getId()).equals("button_calendar")) {
if(isChecked) {
try {
setStateOfApp("calendar","true");
} catch (JSONException e) {
e.printStackTrace();
}
Intent intent = new Intent(context, GoogleApp.class);
((Activity) context).startActivityForResult(intent,10);
} else {
try {
setStateOfApp("calendar","false");
} catch (JSONException e) {
e.printStackTrace();
}
}
}
}
}
} else {
gridView = (View) convertView;
}
return gridView;
}
}
答案 0 :(得分:1)
您正在尝试访问不属于View
内容视图的Activity
。因此,您无法直接访问该视图。
button = (ToggleButton)findViewById(R.id.button_calendar); // will return null
此ToggleButton将为null,因为findViewById将无法在当前内容视图中找到ToggleButton,因为该视图存在于适配器中而不是内容视图中。
你得到nullpointerException,因为你试图在null视图上访问属性。
button.setChecked(true); // This button is null
答案 1 :(得分:0)
在java中,我们有<Future>
,但我不认为这是您正在寻找的内容。
适配器(扩展BaseAdaper
)行为允许您创建适配器,即使在第二时刻,也可以通过getAdapter()。setData()或您选择添加的任何方法来更改基础数据。
从这个角度来看,适配器是一个&#34;愚蠢的&#34;作为A View容器的组件,你应该在别处检索数据(CursorAdapter是不同的)。
因此,在您的Activity中,使用所需数据填充适配器,完成后,调用adapter.notifyDatasetChanged()。这将通知适配器其自己的数据已更改,并且必须刷新视图
答案 2 :(得分:0)
是的,理想情况下,适配器的数量应来自外部。适配器应该只是接收数据列表并将数据映射到视图。例如,Activity中的某些方法或任务可以生成一个数据列表(可能是异步的......因为你提到它)然后传递给适配器然后你可以根据需要通知notifyDataSetChanged()。
我看不到您的代码,但如果由于某种原因确实需要从适配器内部填充数据,您可以使用事件总线并在Activity中订阅它。我建议使用第一个选项,但如果您选择使用事件总线,这里有一些链接:
答案 3 :(得分:0)
根据我对你的问题的理解 您没有正确管理活动中的适配器数据。 如果任何数据或代码与适配器数据或值相互关联 然后,您可以在检索值或数据并更新活动中的视图后启动这些代码。 请注意,在适配器中使用Viewholders可以避免在listviews中缓慢填充和滚动。 观众可以顺利完成您的流程。
我个人建议你这样做 请使用Recyclerview和RecyclerViewAdapter。 很多Android开发人员都在使用它。
如果你在适配器中有后台任务,你可以选择使用RX Java或EventBus
如果您提供代码 我们建议确切的解决方案更好