如何正确实现runOnUiThread Android
Posted
技术标签:
【中文标题】如何正确实现runOnUiThread Android【英文标题】:How to Properly Implement runOnUiThread Android 【发布时间】:2017-09-22 20:11:33 【问题描述】:我需要在从 web 服务获取一些字符串的工作线程中使用 runOnUiThread 更新 UI 中的 TextView。我在这里查看了其他一些帖子并尝试实施提供的解决方案,但是当我启动我的应用程序时它崩溃了。我对这种方法不太熟悉,所以我需要一些指导来解决这个问题。
04-25 12:19:59.917 4108-4108/? I/art: 不延迟启用 -Xcheck:jni (已经启用) 04-25 12:19:59.917 4108-4108/? W/art:使用默认值的 X86 的意外 CPU 变体:x86 04-25 12:20:00.147 4108-4108/com.example.gmars.parseltonguev2 W/系统:类加载器引用未知路径:/data/app/com.example.gmars.parseltonguev2-2/lib/x86 04-25 12:20:00.154 4108-4108/com.example.gmars.parseltonguev2 I/InstantRun: 启动即时运行服务器: 是主进程 04-25 12:20:00.218 4108-4108/com.example.gmars.parseltonguev2 D/androidRuntime: 关闭虚拟机 04-25 12:20:00.218 4108-4108/com.example.gmars.parseltonguev2 E/AndroidRuntime: 致命异常: main 进程:com.example.gmars.parseltonguev2,PID:4108 java.lang.RuntimeException:无法实例化活动 ComponentInfocom.example.gmars.parseltonguev2/com.example.gmars.parseltonguev2.MainActivity:java.lang.NullPointerException:尝试调用虚拟方法 'android.view.Window$Callback android.view.Window.getCallback()' 在空对象引用上 在 android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2548) 在 android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2707) 在 android.app.ActivityThread.-wrap12(ActivityThread.java) 在 android.app.ActivityThread$H.handleMessage(ActivityThread.java:1460) 在 android.os.Handler.dispatchMessage(Handler.java:102) 在 android.os.Looper.loop(Looper.java:154) 在 android.app.ActivityThread.main(ActivityThread.java:6077) 在 java.lang.reflect.Method.invoke(本机方法) 在 com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865) 在 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755) 原因:java.lang.NullPointerException:尝试在空对象引用上调用虚拟方法 'android.view.Window$Callback android.view.Window.getCallback()' 在 android.support.v7.app.AppCompatDelegateImplBase.(AppCompatDelegateImplBase.java:120) 在 android.support.v7.app.AppCompatDelegateImplV9.(AppCompatDelegateImplV9.java:155) 在 android.support.v7.app.AppCompatDelegateImplV11.(AppCompatDelegateImplV11.java:31) 在 android.support.v7.app.AppCompatDelegateImplV14.(AppCompatDelegateImplV14.java:55) 在 android.support.v7.app.AppCompatDelegateImplV23.(AppCompatDelegateImplV23.java:33) 在 android.support.v7.app.AppCompatDelegateImplN.(AppCompatDelegateImplN.java:33) 在 android.support.v7.app.AppCompatDelegate.create(AppCompatDelegate.java:201) 在 android.support.v7.app.AppCompatDelegate.create(AppCompatDelegate.java:185) 在 android.support.v7.app.AppCompatActivity.getDelegate(AppCompatActivity.java:519) 在 android.support.v7.app.AppCompatActivity.findViewById(AppCompatActivity.java:190) 在 com.example.gmars.parseltonguev2.MainActivity.(MainActivity.java:30) 在 java.lang.Class.newInstance(本机方法) 在 android.app.Instrumentation.newActivity(Instrumentation.java:1078) 在 android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2538) 在 android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2707) 在 android.app.ActivityThread.-wrap12(ActivityThread.java) 在 android.app.ActivityThread$H.handleMessage(ActivityThread.java:1460) 在 android.os.Handler.dispatchMessage(Handler.java:102) 在 android.os.Looper.loop(Looper.java:154) 在 android.app.ActivityThread.main(ActivityThread.java:6077) 在 java.lang.reflect.Method.invoke(本机方法) 在 com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865) 在 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)
Activity updateUI;
@Override
public void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
updateUI = this;
itemList = new ArrayList<>();
new GetItemAvailability().execute();
@Override
public Void doInBackground(Void... arg0)
HttpHandler handler = new HttpHandler();
String JSON_DATA = handler.makeServiceCall(url);
Log.e(TAG, "Response from url: " + JSON_DATA);
if (JSON_DATA != null)
JSON_DATA = JSON_DATA.substring(JSON_DATA.indexOf(''),JSON_DATA.lastIndexOf('')+1);
Log.e(TAG, "Substring of response: " + JSON_DATA);
try
JSONObject reader = new JSONObject(JSON_DATA);
JSONObject availability = reader.getJSONObject("availability");
final String availableQuantity = availability.getString("availableQuantity");
final String defaultBranch = availability.getString("defaultBranch");
final String defaultInventoryBranch = availability.getString("defaultInventoryBranch");
final String inventoryBranch = availability.getString("inventoryBranch");
final String footage = availability.getString("footage");
final String anticipatedStockDate = availability.getString("anticipatedStockDate");
final String discontinuedItemFlag = availability.getString("discontinuedItemFlag");
final String mdc = availability.getString("mdc");
final String mdcquantity = availability.getString("mdcquantity");
HashMap<String, String> item = new HashMap<>();
item.put("availableQuantity", availableQuantity);
item.put("defaultBranch", defaultBranch);
item.put("defaultInventoryBranch", defaultInventoryBranch);
item.put("inventoryBranch", inventoryBranch);
item.put("footage", footage);
item.put("anticipatedStockDate", anticipatedStockDate);
item.put("discontinuedItemFlag", discontinuedItemFlag);
item.put("mdc", mdc);
item.put("mdcquantity", mdcquantity);
itemList.add(item);
updateUI.runOnUiThread(new Runnable()
@Override
public void run()
tvAvailableQuantity.setText(availableQuantity);
tvDefaultBranch.setText(defaultBranch);
tvDefaultInventoryBranch.setText(defaultInventoryBranch);
tvInventoryBranch.setText(inventoryBranch);
tvFootage.setText(footage);
tvAnticipatedStockDate.setText(anticipatedStockDate);
tvDiscontinuedItemFlag.setText(discontinuedItemFlag);
tvMdc.setText(mdc);
tvMdcquantity.setText(mdcquantity);
);
【问题讨论】:
必须初始化UI变量,例如TextView tvAvailableQuantity = (TestView) findViewById(id)
你能编辑你的问题并添加崩溃的堆栈跟踪吗?可能与runOnUiThread()
无关,它会为我们提供更多信息。
我已经在 onCreate 方法之前使用我的其他变量完成了该操作。我只发布了有关 runOnUiThread 的代码的 sn-ps。谢谢。
请添加堆栈跟踪...
我添加了堆栈跟踪。
【参考方案1】:
您的 runOnUiThread() 实现是正确的。您将它传递给在 UI 线程上运行的可运行文件。
但是,在您的情况下,如果您将 AsyncTask 的结果类型更改为字符串,我认为这甚至没有必要,您可以简单地从 doInBackground()
方法返回 JSON_DATA
并将其余代码移动到 @987654323 @ 无论如何都在 UI 线程上运行。
【讨论】:
谢谢,我在 onCreate 之前初始化了我的 TextViews。但是,使用 runOnUiThread 或您的方法哪个更好? 通常情况下,如果需要,您可以使用 runOnUiThread,例如当你在不同的线程中做某事时向用户展示一些东西。在您的情况下,您的网络访问(首先需要单独的线程)已经结束,所以在这种情况下,我想说我的建议在这里更可取 - 它也更容易阅读,更短一点,你不需要创建 Runnable 对象。以上是关于如何正确实现runOnUiThread Android的主要内容,如果未能解决你的问题,请参考以下文章
如何等待 Android runOnUiThread 完成?
我们如何在 Android 中使用 runOnUiThread?