我正在尝试从用户的手机中提取联系人,然后将这些联系人与我在解析后端中的电话号码进行匹配,然后在自定义列表视图中显示匹配项。我已经设法做了几乎所有事情,但是我无法正确设置全局变量mBinderPhoneNumber。无论出于何种原因,根据logcat,变量首先显示为null,并且稍后才获得正确的值,即使我在需要使用它之前正确设置变量。
这是logcat,它显示变量首先显示为null,然后才在以后正确设置:
12-31 15:17:12.242 27804-27935/com.rileymacdonaldapps.binder D/TAG: mBinderPhoneNumbers from AddContactsInList:null
12-31 15:17:12.902 27804-27804/com.rileymacdonaldapps.binder D/TAG: mBinderPhoneNumbers from onCreate: [CORRECT PARSE USER1, CORRECT PARSE USER2]
有人可以帮助我吗?
这是活动:
public class AddContactsActivity extends Activity {
public List mBinderPhoneNumbers;
Context context = null;
ContactsAdapter objAdapter;
ListView lv = null;
EditText edtSearch = null;
LinearLayout llContainer = null;
Button btnOK = null;
RelativeLayout rlPBContainer = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
context = this;
setContentView(R.layout.activity_add_contacts);
rlPBContainer = (RelativeLayout) findViewById(R.id.pbcontainer);
edtSearch = (EditText) findViewById(R.id.input_search);
llContainer = (LinearLayout) findViewById(R.id.data_container);
btnOK = (Button) findViewById(R.id.ok_button);
btnOK.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
getSelectedContacts();
}
});
edtSearch.addTextChangedListener(new TextWatcher() {
@Override
public void onTextChanged(CharSequence cs, int arg1, int arg2,
int arg3) {
// When user changed the Text
String text = edtSearch.getText().toString()
.toLowerCase(Locale.getDefault());
objAdapter.filter(text);
}
@Override
public void beforeTextChanged(CharSequence arg0, int arg1,
int arg2, int arg3) {
// TODO Auto-generated method stub
}
@Override
public void afterTextChanged(Editable arg0) {
// TODO Auto-generated method stub
}
});
// Get parse users
String [] phoneNumberList = {"DUMMY NUMBER1", "DUMMY NUMBER2", "DUMMY NUMBER3", "DUMMY NUMBER4"};
ParseQuery<ParseUser> query = ParseUser.getQuery(); {
query.whereContainedIn("username", Arrays.asList(phoneNumberList));
query.findInBackground(new FindCallback<ParseUser>() {
public void done (List<ParseUser> list, ParseException e){
if (e == null) {
mBinderPhoneNumbers = list;
Log.d("TAG", "mBinderPhoneNumbers from onCreate: " + mBinderPhoneNumbers);
} else {
// Something went wrong.
Log.e("TAG", "User query error: " + e);
}
}
});
}
addContactsInList();
}
private void getSelectedContacts() {
// TODO Auto-generated method stub
StringBuffer sb = new StringBuffer();
for (ContactObject bean : ContactsListClass.phoneList) {
if (bean.isSelected()) {
sb.append(bean.getName());
sb.append(",");
}
}
String s = sb.toString().trim();
if (TextUtils.isEmpty(s)) {
Toast.makeText(context, "Select at least one Contact",
Toast.LENGTH_SHORT).show();
} else {
s = s.substring(0, s.length() - 1);
Toast.makeText(context, "Selected Contacts: " + s,
Toast.LENGTH_SHORT).show();
}
}
private void addContactsInList() {
// TODO Auto-generated method stub
Thread thread = new Thread() {
@Override
public void run() {
showPB();
try {
Cursor phones = getContentResolver().query(
ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
null, null, null, null);
try {
ContactsListClass.phoneList.clear();
} catch (Exception e) {
}
while (phones.moveToNext()) {
Log.d("TAG", "mBinderPhoneNumbers from AddContactsInList:" + mBinderPhoneNumbers);
if (Arrays.asList(mBinderPhoneNumbers).contains(phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NORMALIZED_NUMBER)))) {
String phoneName = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
String phoneNumber = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NORMALIZED_NUMBER));
String phoneImage = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.CONTACT_ID));
ContactObject cp = new ContactObject();
cp.setName(phoneName);
cp.setNumber(phoneNumber);
cp.setImage(phoneImage);
ContactsListClass.phoneList.add(cp);
}
}
phones.close();
lv = new ListView(context);
lv.setLayoutParams(new LayoutParams(
LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT));
runOnUiThread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
llContainer.addView(lv);
}
});
Collections.sort(ContactsListClass.phoneList,
new Comparator<ContactObject>() {
@Override
public int compare(ContactObject lhs,
ContactObject rhs) {
return lhs.getName().compareTo(
rhs.getName());
}
});
objAdapter = new ContactsAdapter(AddContactsActivity.this,
ContactsListClass.phoneList);
lv.setAdapter(objAdapter);
lv.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent,
View view, int position, long id) {
CheckBox chk = (CheckBox) view
.findViewById(R.id.contactcheck);
ContactObject bean = ContactsListClass.phoneList
.get(position);
if (bean.isSelected()) {
bean.setSelected(false);
chk.setChecked(false);
} else {
bean.setSelected(true);
chk.setChecked(true);
}
}
});
} catch (Exception e) {
e.printStackTrace();
}
hidePB();
}
};
thread.start();
}
void showPB() {
runOnUiThread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
rlPBContainer.setVisibility(View.VISIBLE);
edtSearch.setVisibility(View.GONE);
btnOK.setVisibility(View.GONE);
}
});
}
void hidePB() {
runOnUiThread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
rlPBContainer.setVisibility(View.GONE);
edtSearch.setVisibility(View.VISIBLE);
btnOK.setVisibility(View.VISIBLE);
}
});
}
}
答案 0 :(得分:0)
query.findInBackground(new FindCallback<ParseUser>() {
public void done (List<ParseUser> list, ParseException e){
if (e == null) {
mBinderPhoneNumbers = list;
addContactsInList();// call here
Log.d("TAG", "mBinderPhoneNumbers from onCreate: " + mBinderPhoneNumbers);
} else {
// Something went wrong.
Log.e("TAG", "User query error: " + e);
}
}
});
最好像这样使用。由于您使用的是findInBackground
,因此会有延迟。该列表仅在调用done
后才可用。
答案 1 :(得分:0)
query.findInBackground()
和addContactsInList()
都异步执行工作。一旦你打电话给他们,他们就会启动一个后台线程来完成工作。因为您按顺序调用这两个方法,所以两个线程几乎同时启动。你不能保证何时哪一种方法相对于另一种方法完成。
听起来你想要的只是在addContactsInList()
完成后才调用query.findInBackground()
。将该调用移至findInBackground()
的{{1}}回调应该可以达到预期的效果。
答案 2 :(得分:0)
问题是,query.findInBackground()
正在其自己的线程中执行。由于它不是阻塞调用,因此主线程不会等待query.findInBackground()
完成。因此,addContactsInList()
即使在mBinderPhoneNumbers
初始化之前也会开始执行。
更好的解决方案是在addContactsInList()
内拨打done()
。像这样,
query.findInBackground(new FindCallback<ParseUser>() {
public void done (List<ParseUser> list, ParseException e){
if (e == null) {
mBinderPhoneNumbers = list;
addContactsInList();
.....
}
}
});