这是我的主要活动:
public class LearnTree extends AppCompatActivity {
private RulesFragment rulesFragment;
private TreeFragment treeFragment;
private PredictionFragment predictionFragment;
TabLayout tabLayout;
ViewPager viewPager;
private Button button;
private static ObjectOutputStream out;
private static ObjectInputStream in;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.learn_tree);
tabLayout=findViewById(R.id.tab_layout);
viewPager= findViewById((R.id.view_pager));
final ViewPagerAdapter viewPagerAdapter= new ViewPagerAdapter(getSupportFragmentManager());
viewPagerAdapter.addFragment(RulesFragment.getInstance(), "TREE RULES");
viewPagerAdapter.addFragment(TreeFragment.getInstance(), "REGRESSION TREE");
viewPagerAdapter.addFragment(PredictionFragment.getInstance(), "PREDICTION");
rulesFragment= (RulesFragment) viewPagerAdapter.getItem(0);
treeFragment= (TreeFragment) viewPagerAdapter.getItem(1);
predictionFragment= (PredictionFragment) viewPagerAdapter.getItem(2);
viewPager.setAdapter(viewPagerAdapter);
tabLayout.setupWithViewPager(viewPager);
LearnTree.PrimeThread p=new LearnTree.PrimeThread();
p.start();
}
private class PrimeThread extends Thread {
public void run() {
out= SocketObject.getOut();
in = SocketObject.getIn();
// print rules
rulesFragment.setText((String)in.readObject());
//print tree
treeFragment.setText((String)in.readObject());
}
}
}
这是我的三个片段之一,其他两个几乎相同:
public class RulesFragment extends Fragment {
// Store instance variables
private String title;
private int page;
private TextView rulesView;
public static RulesFragment getInstance() {
RulesFragment rulesFragment = new RulesFragment();
return rulesFragment;
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view= inflater.inflate(R.layout.rules_fragment, container, false);
rulesView= (TextView) view.findViewById(R.id.textview_treerules);
rulesView.setMovementMethod(new ScrollingMovementMethod());
return view;
}
public void setText(String text){
rulesView.setText(text);
}
}
当执行规则Fragment.setText((String)in.readObject());
我得到这个错误:只有创建视图层次结构的原始线程可以触摸它的视图
那是因为我在onCreateView中创建了文本视图,但我正在setText中编辑它,对吗?问题是我需要在程序执行期间多次编辑该文本,并且我不能在onCreateView中传输我的部分代码(让它像一个单独的线程一样运行,我猜?)因为我需要按顺序从Socket检索输入。
还有别的办法吗?
此外,假设我在第三个片段中有一个旋转器和一个按钮“Send”。当用户点击Send时,我应该将每个片段中的每个textview重置为空,并且我需要在LearnTree类中的PrimeThread中重新启动执行。我该怎么做?有没有办法从主活动中检测发送按钮的onClick事件?
为了回答您的主要问题,正在发生的事情是创建视图的线程是Main UI线程。出于这个原因,每当您想从不同的线程(在您的情况下是PrimeThread)更改UI上的某些内容时,您应该使用runOnUiThread
执行函数。
这意味着您的代码中应该包含:
String rules = (String)in.readObject()
String tree = (String)in.readObject()
requireActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
// print rules
rulesFragment.setText(rules);
//print tree
treeFragment.setText(tree);
}
});
对于您最后一个关于让侦听器单击按钮的问题,您可以这样做:
Button buttonY = (Button)findViewById(R.id.buttonYName);
// Register the onClick listener with the implementation above
buttonY.setOnClickListener(new OnClickListener() {
public void onClick(View v)
{
(LearnTree)getActivity().primeThread.start(); // Assuming this is executed in the context of a Fragment
}
});
如果要重新启动LearnTree活动中的线程,需要将该线程存储在类变量中:
public LearnTree.PrimeThread primeThread;
或者将其声明为私有并拥有getter/setter,这取决于您。
此外,您应该像这样创建您的ViewPagerAdapter,否则您将遇到崩溃:
public class ViewPagerAdapter extends FragmentPagerAdapter {
public ViewPagerAdapter(FragmentManager fragmentManager) {
super(fragmentManager);
}
@Override
public Fragment getItem(int position) {
if(position == 0) return new RulesFragment();
if(position == 1) return new TreeFragment();
if(position == 2) return new PredictionFragment();
throw new IllegalStateException("Unexpected position " + position);
}
@Override
public int getCount() {
return 3;
}
@Override
public CharSequence getPageTitle(int position) {
if(position == 0) return "TREE RULES";
if(position == 1) return "REGRESSION TREE";
if(position == 2) return "PREDICTION";
throw new IllegalStateException("Unexpected position " + position);
}
}
要获取对ViewPager创建的片段的引用,请使用以下findFragmentByTag方案:
Fragment fragment = supportFragmentManager.findFragmentByTag("android:switcher:" + viewPager.getId() + ":" + fragmentPosition)
前面的答案非常完整。但是,您可以尝试调用:
Device.BeginInvokeOnMainThread(
() => { lblStatus.Text = "Updating..."; }
);
我正在使用MultipartEntityBuilder将图像发送到php服务器,我将图片和视频发送到设备摄像头的目录中,我需要将文件保存在新的ArrayList上并将其发送到php服务器。 总是报告错误: 我的代码 更新
我在Android中构建了一个简单的音乐播放器。每首歌的视图都包含一个SeekBar,实现如下: 这很好用。现在我想要一个计时器来计算歌曲进度的秒/分钟。因此,我在布局中放置了一个文本视图,在onCreate()中使用findViewById()获取它,并在。设置进度(pos): 但最后一行给了我一个例外: Android看法ViewRoot$CalledFromErrorThreadExcept
这是我所有的代码。
我有一个错误,只有创建视图层次结构的原始线程才能接触它的视图。但我不知道如何在多线程中处理ui,比如列表视图,我也不知道该放在哪里。
我正在为小应用程序设计UnitTest。这个应用程序说明您使用的是什么命理数字出生日期。我有一个问题,我该调用检查数字并将值放入TextView的方法。我有一个错误 ' 我的布局:` 我想测试的方法:'
得到一个错误:android.view.ViewRootImpl$CalledFromWrongThreadException:只有创建视图层次结构的原始线程可以触摸它的视图。 我真的不知道为什么。 谢谢帮忙。