如何从线程更新 UI?
Posted
技术标签:
【中文标题】如何从线程更新 UI?【英文标题】:How to updated UI from thread? 【发布时间】:2013-10-12 07:22:19 【问题描述】:我在 android app 中使用线程时遇到了一些问题。
我有 Activity1.java,它有一些从 sql lite 数据库获取数据并将其显示在活动上的功能。我有一种方法 Load() 填充一些微调器静态和一些来自数据库。第二个微调器值取决于第一个下拉菜单,依此类推。它还可见/不可见一些 UI 控件
场景 1:-
如果我们在 oncreate() 方法上调用 Load() 函数,那么活动会变慢。
场景2:-(线程)
如果我们在 oncreate() 方法的线程内调用 Load() 函数并且我使用 runOnUiThread 或 Handler.post 来更新 ui 控件,那么它将跳过该代码,在代码中走得更远,而我的其他值有些错误或来不及。
场景 3:-(异步)
如果我们在 oncreate() 方法上调用 Aysnc 中的 Load() 函数,那么我必须从异步任务中不断更新 ui。 UI 中的更新只允许在 onPostExecute(Result) 和 onProgressUpdate(Progress...) 上进行,但我如何从 async 连续更新 ui。
@Override
protected void onCreate(Bundle savedInstanceState)
BindStaticValues();
GetCalculationOptions();
public void BindStaticValues()
//standard
BindStandard(); //static spinner (not db)
//Spinner 1
array1 = new ArrayList<ObjectMaterial>();
Adapter1 = new DescriptionAdapter(this,
android.R.layout.simple_spinner_item,
array1 );
Adapter1
.setDropDownViewResource(android.R.layout.simple_spinner_item);
sp1.setAdapter(Adapter1 );
//Spinner 2
array2 = new ArrayList<ObjectMaterial>();
Adapter2 = new DescriptionAdapter(this,
android.R.layout.simple_spinner_item,
array2 );
Adapter2
.setDropDownViewResource(android.R.layout.simple_spinner_item);
sp2.setAdapter(Adapter2 );
public void GetCalculationOptions ()
progressCalcualtionOptions = ProgressDialog.show(context, getString(R.string.progressCalcualtionOptionsTitle),
getString(R.string.progressCalcualtionOptionsMessage), true);
new Thread(new Runnable()
public void run()
try
LoadValuesforFirstTime(false, false, false); //main load method (Need Updating UI)
isFirstOpen=false;
catch (Exception e)
//Log.d(Constants.TAG, e.getMessage());
e.printStackTrace();
if (progressCalcualtionOptions != null)
progressCalcualtionOptions.dismiss();
progressCalcualtionOptions=null;
).start();
private void LoadValuesforFirstTime(Boolean FromMaterial,
Boolean FromLangugae, Boolean FromCountry)
ChangeVisibility(); // it will change visibility of some controls
FillSpinner1(TypeofMaterial); //fill first spinner 1
FillSpinner2(ObjectMaterial); //fill first spinner 2 (take values from spinner 1 or manipulate values in spinner 1)
private void ChangeVisibility()
// it will change visibility of some controls
runOnUiThread(new Runnable()
public void run()
relat_heightPipe.setVisibility(View.GONE);
relat_PipeDiameter.setVisibility(View.GONE);
relat_WidthPipe.setVisibility(View.GONE);
relat_length.setVisibility(View.GONE);
relat_lblMediumHeatCapacity.setVisibility(View.GONE);
relat_lblMediumDensity.setVisibility(View.GONE);
);
private void FillSpinner1(String TypeofMaterial)
array1 = DB_Manager.All(); //get from db
h.post(new Runnable()
public void run()
Adapter1.clear();
for (ObjectMaterial object : array1 )
Adapter1.add(object);
Adapter1.notifyDataSetChanged();
);
private void FillSpinner2(String TypeofMaterial)
array2 = DB_Manager.All1(spinner1.getSelectedItemPosition()); //get from db
h.post(new Runnable()
public void run()
Adapter2.clear();
for (ObjectMaterial object : array2 )
Adapter2.add(object);
Adapter2.notifyDataSetChanged();
);
现在,问题是:-
当活动打开时,GetCalculationOptions 调用一个线程来填充所有微调器值。在此它调用 LoadValuesforFirstTime() 函数。在这里我用 db 和 ui 做所有事情。 这里 changevisibility 更改某些控件的可见性,FillSpinner1 填充从 db 获取值,在主 ui 线程内刷新适配器,填充 Spinenr2 根据微调器 1 中的选定值从 db 获取值,但在微调器 1 中找不到值,因为它直到没有填充现在它是另一个线程,现在我们必须从 LoadValuesforFirstTime() 函数不断更新 UI。
任何人,请帮助我或建议我任何其他选择来实现这一目标。
【问题讨论】:
【参考方案1】:调用你的方法
runOnUiThread(new Runnable()
public void run()
write your method here
);
来自doInbackground
方法。
【讨论】:
如果我在主 ui 线程上运行所有功能,那么活动会变慢。 只需在负责更新ui的run方法中调用该方法。以上是关于如何从线程更新 UI?的主要内容,如果未能解决你的问题,请参考以下文章