我在android中的后台线程中执行后台操作,如下所示:
switch (position) {
final List<Profile> filteredList = new ArrayList<>(0);
case BELATED:
Runnable belatedRunnable = new Runnable() {
@Override
public void run() {
for (Profile profile : allBirthdayProfiles) {
String birthday = profile.getBirthday();
String[] values = birthday.split("-");
int day = Integer.parseInt(values[0]);
int month = Integer.parseInt(values[1]);
SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy");
Calendar calendar = Calendar.getInstance();
String currentDate = formatter.format(calendar.getTime());
String[] currentDateValues = currentDate.split("-");
int currentDay = Integer.parseInt(currentDateValues[0]);
int currentMonth = Integer.parseInt(currentDateValues[1]);
if (month < currentMonth)
filteredList.add(profile);
else if (month == currentMonth && day < currentDay)
filteredList.add(profile);
Log.d(TAG, filteredList + " IN THREAD");
}
}
};
Thread belatedThread = new Thread(belatedRunnable);
belatedThread.setName("FilterBelatedThread");
belatedThread.start();
break;
default:
return allBirthdayProfiles;
}
Log.d(TAG, filteredList + " END RESULT");
return filteredList;
}
由于代码将配置文件附加到已过滤列表(List<Profile> filteredList
),因此应该在线程运行时修改filteredList.add(profile
。
在这个switch语句之外我返回filteredList,理论上它应该是非null,因为运行了if
语句(满足条件),但是filteredList是空的。
D/BirthdayFilter: [] END RESULT
D/BirthdayFilter: [{"birthday":"02-08-2016","favouriteIds":["62InvCZG9jaEmUNiJsssTIjImqY2"],"firstName":"Edal","friendIds":["62InvCZG9jaEmUNiJsssTIjImqY2"],"lastName":"Grunt","userId":"62InvCZG9jaEmUNiJsssTIjImqY2"}]IN THREAD
为什么filterList为空,即使我在线程中更新它?
答案 0 :(得分:4)
这是您在此遇到的经典并发问题。 run
Runnable
方法中的代码与主代码并行执行(这是Runnable
和Thread
s的全部目的)。因此,Java Runtime无法保证执行顺序!有时你的if语句将在return语句之前进行评估,大部分时间都是相反的。
您可能想要做的是通知主线程您在run
方法中所做的更改。根据您的设置,这可能与此类似:
Runnable belatedRunnable = new Runnable() {
@Override
public void run() {
// ... normal code here
updateList(); // notify main thread of changes
}
}
然后为您的活动添加一个新方法,根据需要更新列表:
private void updateList() {
// update your list
}
或者,如果您将此作为独立组件使用,则需要将侦听器传递给该方法,以便它可以通知调用方更改。例如,创建一个新界面:
public interface Updateable {
void update();
}
然后在您的调用类中实现此接口,例如:
public MyFragment extends Fragment implements Updateable {
// ...
@Override
public void update() {
// update your list here
}
}
然后将其添加到您的方法中:
public void filter(/* ... */ final Updateable listener) {
// inside your run method:
listener.update();
}
最后在你的调用类中调用你的方法,如下所示:
filter(/* ... */ this);
您可能需要考虑将列表传递给update
接口和方法,以便直接使用新数据更新列表。
或者,如果这是一项耗时的后台操作,您可能需要考虑使用AsyncTask
,其onPostExecute
方法使其易于使用。